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+2
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 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 - 每季度不同客户的运行计数的主要内容,如果未能解决你的问题,请参考以下文章

计数SQL,查找单据总量和按季度查找单据总量

SQL 按小时获取不同的客户计数

SQL SERVER分区具体例子详解

计数与季度聚合不同

如何在一个 SQL Server 查询中组合不同的计数

如何使用sql server查询前8个季度的季度数据报表?