2016-08-04 2 views
1

я хотел бегущий подсчет различного с перегородкой в ​​году для следующих данных:Запуск Distinct Count с Partition

DROP TABLE IF EXISTS #FACT; 
CREATE TABLE #FACT("Year" INT,"Month" INT, "Acc" varchar(5)); 
INSERT INTO #FACT 
    values 
     (2015, 1, 'A'), 
     (2015, 1, 'B'), 
     (2015, 1, 'B'), 
     (2015, 1, 'C'), 
     (2015, 2, 'D'), 
     (2015, 2, 'E'), 
     (2015, 3, 'E'), 
     (2016, 1, 'A'), 
     (2016, 1, 'A'), 
     (2016, 2, 'B'), 
     (2016, 2, 'C'); 
SELECT * FROM #FACT;  

Следующих возвращает правильный ответ, но есть более краткий путь, который также производительный?

WITH 
dnsRnk AS 
(
    SELECT 
     "Year" 
     , "Month" 
     , DenseR = DENSE_RANK() OVER(PARTITION BY "Year", "Month" ORDER BY "Acc") 
    FROM #FACT 
), 
mxPerMth AS 
(
    SELECT 
     "Year" 
     , "Month" 
     , RunningTotal = MAX(DenseR) 
    FROM dnsRnk 
    GROUP BY 
     "Year" 
     , "Month" 
) 
SELECT 
    "Year" 
    , "Month" 
    , X = SUM(RunningTotal) OVER (PARTITION BY "Year" ORDER BY "Month") 
FROM mxPerMth 
ORDER BY 
    "Year" 
    , "Month"; 

Вышеприведенных возвращает следующее - ответ должен также вернуть точно такую ​​же таблицу:

enter image description here

+0

Вы можете редактировать этот вопрос и показать желаемые результаты? –

+0

@ GordonLinoff предоставлено сейчас: ответ должен возвращать то же самое – whytheq

ответ

1

Если вы хотите бегущий подсчет различных счетов:

select f.*, 
     sum(case when seqnum = 1 then 1 else 0 end) over (partition by year order by month) as cume_distinct_acc 
from (select f.*, 
      row_number() over (partition by account order by year, month) as seqnum 
     from #fact f 
    ) f; 

Этого подсчитывает каждую учетную запись в течение первого месяца, когда она появляется.

EDIT:

Упс. Вышеуказанное не агрегируется по годам и месяцам, а затем начинается за каждый год. Вот правильное решение:

select yyyy, mm, 
     sum(sum(case when seqnum = 1 then 1 else 0 end) 
     ) over (partition by year order by month) as cume_distinct_acc 
from (select f.*, 
      row_number() over (partition by account, year order by month) as seqnum 
     from #fact f 
    ) f 
group by year, month 
order by year, month; 

И SQL Скрипки не работает, но следующий пример:

with FACT as (
    SELECT yyyy, mm, account 
    FROM (values 
     (2015, 1, 'A'), 
     (2015, 1, 'B'), 
     (2015, 1, 'B'), 
     (2015, 1, 'C'), 
     (2015, 2, 'D'), 
     (2015, 2, 'E'), 
     (2015, 3, 'E'), 
     (2016, 1, 'A'), 
     (2016, 1, 'A'), 
     (2016, 2, 'B'), 
     (2016, 2, 'C')) v(yyyy, mm, account) 
    ) 
select yyyy, mm, 
     sum(sum(case when seqnum = 1 then 1 else 0 end)) over (partition by yyyy order by mm) as cume_distinct_acc 
from (select f.*, 
      row_number() over (partition by account, yyyy order by mm) as seqnum 
     from fact f 
    ) f 
group by yyyy, mm 
order by yyyy, mm; 
+0

Я думаю, что это хороший подход, но в настоящее время он не возвращает тот же результат, что и скрипт в вопросе: результаты должны быть одинаковыми – whytheq

1

Demo Here:

;with cte 
as 
(select yearr,monthh,count(distinct acc) as cnt from #fact 
group by yearr,monthh 
) 
select yearr,monthh, 
sum(cnt) over (Partition by yearr order by yearr,monthh rows unbounded preceding) as x 
from cte 
+0

это что-то поддерживается после SQL Server 2012 ? –

+0

Он поддерживает SQLServer 2012, если это то, о чем вы просите – TheGameiswar

+0

Пробовал использовать его, дал мне ошибку: 'Некорректный синтаксис около 'preceeding'' –