2014-08-29 28 views
6

używam poniżej zapytania znaleźć mediany dla każdego sektoraZnalezienie Mediana w serwerze sql września każdy dzień w tabeli

SELECT DISTINCT Sector, 
    PERCENTILE_DISC(0.5) WITHIN 
GROUP (ORDER BY Value) OVER (PARTITION BY sector) AS Median 
FROM TABLE 

Stół jest w poniżej formatu

Sector Date Value 
    A 2014-08-01 1 
    B 2014-08-01 5 
    C 2014-08-01 7 
    A 2014-08-02 6 
    B 2014-08-02 5 
    C 2014-08-02 4 
    A 2014-08-03 3 
    B 2014-08-03 9 
    C 2014-08-03 6 
    A 2014-08-04 5 
    B 2014-08-04 8 
    C 2014-08-04 9 
    A 2014-08-05 5 
    B 2014-08-05 7 
    C 2014-08-05 2 

Więc uzyskać oczekiwany wynik poniżej:

Sector Median 
    A 5 
    B 7 
    C 6 

Teraz muszę zmienić proces tak, aby medianie były obliczane, a jedynie uwzględniać zadzwoń do rekordów do podanej daty. Tak więc nowy wynik byłby następujący:

Sector Date Value 
    A 2014-08-01 1 
    B 2014-08-01 5 
    C 2014-08-01 7 (Only 1 record each was considered for A, B and C) 

    A 2014-08-02 3.5 
    B 2014-08-02 5 
    C 2014-08-02 5.5 (2 records each was considered for A, B and C) 

    A 2014-08-03 3 
    B 2014-08-03 5 
    C 2014-08-03 6 (3 records each was considered for A, B and C) 

    A 2014-08-04 4 
    B 2014-08-04 6.5 
    C 2014-08-04 6.5 (4 records each was considered for A, B and C) 

    A 2014-08-05 5 
    B 2014-08-05 7 
    C 2014-08-05 6 (All 5 records each was considered for A, B and C) 

To będzie trochę skumulowana mediana. Czy ktoś może mi powiedzieć, jak to osiągnąć. Moja tabela ma około 2,3 miliona rekordów z około 1100 rekordami na około 1100 dat.

Proszę dać mi znać, jeśli potrzebujesz jakichkolwiek informacji.

Odpowiedz

1

sprawia, że ​​trudniej, ponieważ następuje nie działa:

SELECT DISTINCT Sector, Date, 
     PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY Value) OVER (PARTITION BY sector ORDER BY DATE) AS Median 
FROM TABLE; 

Alas. Można użyć cross apply do tego celu:

select t.sector, t.date, t.value, m.median 
from table t cross apply 
    (select top 1 PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY t2.Value) OVER (PARTITION BY sector ORDER BY t2.DATE) AS Median 
     from table t2 
     where t2.sector = t.sector and t2.date <= t.date 
    ) m; 
+0

Szanowny Panie, dziękuję. Wydaje się, że działa to dobrze w moim zestawie danych testowych. Teraz używam go przeciwko ogromnemu stołowi. Miejmy nadzieję, że wszystko pójdzie dobrze. Dziękuję bardzo za Twoją pomoc. – John

2

Innym sposobem jest stworzenie trójkątny JOIN aby uzyskać wszystkie wartości w przeszłości dla każdego dnia i użyć jej jako dane

;With T AS (
    SELECT t2.Sector, t2.[Date], t1.[Value] 
    FROM Table1 t1 
     LEFT JOIN Table1 t2 ON t1.Sector = t2.Sector and t1.[Date] <= t2.[Date] 
) 
SELECT DISTINCT Sector 
    , [Date] 
    , PERCENTILE_CONT(0.5) 
     WITHIN GROUP (ORDER BY [Value]) 
     OVER (PARTITION BY sector, [Date]) AS Median 
FROM T 
ORDER BY [Date], Sector; 

SQLFiddle demo

W zapytaniu zmieniono PERCENTILE_DISC z PERCENTILE_CONT, aby uzyskać odpowiednią medianę w przypadku parzystej liczby wartości, na przykład drugi dzień.

+0

Szanowny Panie, dziękuję za odpowiedź. Zmieniłem swój PERCENTILE_DISC na PERCENTILE_CONT – John