SQL Server - 每季度不同客户的运行计数
Posted
技术标签:
【中文标题】SQL Server - 每季度不同客户的运行计数【英文标题】:SQL Server - Running count of distinct customers per quarter 【发布时间】:2019-03-12 18:19:13 【问题描述】:我正在尝试从包含跨季度和季度内重复的表中按季度滚动客户计数。我想只计算在季度内累积的客户的第一次出现。 下面的代码给了我错误的答案 - 它只计算每个季度的不同客户,而不是累积。
DROP TABLE IF EXISTS #FACT;
CREATE TABLE #FACT("FYQ" VARCHAR(10), "GUN" varchar(5));
INSERT INTO #FACT
VALUES
('FY2015Q1', 'A'),
('FY2015Q1', 'B'),
('FY2015Q1', 'B'),
('FY2015Q2', 'C'),
('FY2015Q2', 'D'),
('FY2015Q2', 'E'),
('FY2015Q2', 'E'),
('FY2015Q2', 'A'),
('FY2015Q3', 'F'),
('FY2015Q3', 'G'),
('FY2015Q3', 'C');
SELECT * FROM #FACT;
WITH CTE
AS
(SELECT FYQ, COUNT(DISTINCT GUN) AS CNT
FROM #FACT
GROUP BY FYQ
)
SELECT FYQ,
SUM(CNT) OVER (PARTITION BY FYQ ORDER BY FYQ ROWS UNBOUNDED PRECEDING) AS RollingCustCount
FROM CTE;
数据中四分之三的正确答案是 2、5、7。 谢谢!
【问题讨论】:
“正确答案将是 2,5,7”是什么意思? Q1 包含 2new,Q2 包含 2+3new,Q3 包含 2+3+2new 客户? 正确 - Q1 = A 和 B - 2 个客户。 Q2 = A、B、C、D、E - 5 个客户。 Q3 = A、B、C、D、E、F、G - 7 个客户。 【参考方案1】:我在这里:
num_cust cte: - 按财务季度的顺序对客户代码的出现次数(跨所有季度)进行编号。这意味着 Q1 中的 A 编号为 1,Q2 中的 A 编号为 2。 sum_cust cte - 仅提取 gun_no 为 1 的那些(该季度新发现的客户),对它们进行分组和求和(作为计数 - 也可以使用 COUNT(*))给出 2, 3、2 选择查询 - 建立计数新客户的滚动总和,即 2、2+3、2+3+2DROP TABLE IF EXISTS #FACT;
CREATE TABLE #FACT("FYQ" VARCHAR(10), "GUN" varchar(5));
INSERT INTO #FACT
VALUES
('FY2015Q1', 'A'),
('FY2015Q1', 'B'),
('FY2015Q1', 'B'),
('FY2015Q2', 'C'),
('FY2015Q2', 'D'),
('FY2015Q2', 'E'),
('FY2015Q2', 'E'),
('FY2015Q2', 'A'),
('FY2015Q3', 'F'),
('FY2015Q3', 'G'),
('FY2015Q3', 'C');
SELECT * FROM #FACT;
WITH num_cust AS (
SELECT fyq, ROW_NUMBER() OVER(PARTITION BY gun ORDER BY fyq, gun) as gun_no
FROM #fact
),
sum_cust AS (
SELECT fyq, SUM(gun_no) as sum_gun_no
FROM num_cust
WHERE gun_no = 1
GROUP BY fyq
)
SELECT
fyq,
SUM(sum_gun_no) OVER (ORDER BY fyq ROWS UNBOUNDED PRECEDING) AS RollingCustCount
FROM sum_cust
【讨论】:
效果很好。谢谢!【参考方案2】:一个简单的方法使用apply
:
select q.fyq, distinct_gun
from (select distinct fyq from #fact) as q cross apply
(select count(distinct gun) as distinct_gun
from #fact f
where f.fyq <= q.fyq
) q;
或者,如果你计算第一次出现,我会这样做:
select fyq, count(*) as starts_this_quarter,
sum(count(*)) over (order by fyq
from (select f.*,
row_number() over (partition by gun order by fyq) as seqnum
from #fact f
) f
where seqnum = 1
group by fyq
order by fyq
【讨论】:
以上是关于SQL Server - 每季度不同客户的运行计数的主要内容,如果未能解决你的问题,请参考以下文章