SQL Server:按月汇总,有间隔

Posted

技术标签:

【中文标题】SQL Server:按月汇总,有间隔【英文标题】:SQL Server : aggregate by month with gaps 【发布时间】:2018-01-03 16:34:30 【问题描述】:

我需要一些帮助来汇总一些数据。想象一下,我有下表:

            Employee    Reference Period
            123440      20141201
            123440      20150101
            123440      20150201
            123440      20150301
            123440      20160201
            123440      20160301
            123440      20160401
            123440      20160501
            123440      20160601
            123440      20160701
            123440      20160801
            123440      20160901
            123440      20161001
            123442      20141201
            123442      20150101
            123442      20150201
            123442      20150301
            123442      20150401
            123442      20150501
            123442      20150601
            123442      20150701
            123442      20150801
            123442      20150901
            123442      20151001
            123442      20151101
            123442      20151201
            123442      20170301
            123442      20170401
            123442      20170501
            123442      20170601
            123442      20170701
            123442      20170801
            123442      20170901
            123442      20171001
            123442      20171101
            123442      20171201

我需要一个 SQL 查询来输出以下内容:

Employee    From_Date   To_Date
123440      20141201    20150301
123440      20160201    20161001
123442      20141201    20151201
123442      20170301    20171201

基本上我需要的是加入没有月份间隔的行,并在序列中将[From Date] 作为 MIN() 返回,在序列中将[To Date] 作为 MIN() 返回。谁能帮帮我?

我尝试执行以下查询:

;WITH CTE
     AS (SELECT [Employee], t1refer, t2refer, DIFF,
                Grp2 = ROW_NUMBER()OVER(partition BY [Employee],DIFF ORDER BY t1refer),
                Grp = ROW_NUMBER()OVER(partition BY [Employee],DIFF ORDER BY t1refer) - DIFF
          FROM (
            SELECT DISTINCT t1.[Employee], t1.[Reference Period] t1refer , t2.[Reference Period] t2refer, DATEDIFF(MONTH, CONVERT(DATE,CONVERT(VARCHAR(10),(t2.[Reference Period]+'01'),101)),CONVERT(DATE,CONVERT(VARCHAR(10),(t1.[Reference Period]+'01'),101))) AS DIFF
            FROM MyTable t1 
                CROSS APPLY 
                (SELECT TOP 1 t.[Reference Period] FROM MyTable t 
                    WHERE t.[Employee] = t1.[Employee] AND CONVERT(date,CONVERT(VARCHAR(10),(t.[Reference Period]+'01'),101)) < CONVERT(date,CONVERT(VARCHAR(10),(t1.[Reference Period]+'01'),101)) ORDER BY t.[Reference Period] DESC) t2
            ) QRY
            )
        SELECT [Employee],
       [From Date] = MIN(t2refer),
       [To Date] = MAX(t1refer)     
         FROM CTE   
         GROUP BY [Employee], DIFF 

注意数据库是SQL Server 2008。

【问题讨论】:

检查更新的代码..原始代码有问题 【参考方案1】:

另一个经典的差距和孤岛问题

;WITH cte
     AS (SELECT a.*,
                Prev_period = b.[Reference Period]
         FROM   Yourtable a
                LEFT JOIN Yourtable b
                       ON a.Employee = b.Employee
                          AND Dateadd(mm, 1, b.[Reference Period]) = a.[Reference Period])
SELECT Employee,
       From_Date = Min([Reference Period]),
       To_Date = Max([Reference Period])
FROM   cte a
       CROSS apply(SELECT Sum(CASE WHEN [Reference Period] = Dateadd(mm, 1, Prev_period) THEN 0 ELSE 1 END)
                   FROM   cte b
                   WHERE  a.Employee = b.Employee
                          AND a.[Reference Period] >= b.[Reference Period]) cs (grp)
GROUP  BY Employee,
          grp 
Demo

【讨论】:

这个答案已被标记为已接受,但我确信这似乎只是因为 OP 示例数据中的巧合。这确实是一个间隙和孤岛问题,但 DENSE_RANK 需要替换为将月份转换为整数的东西,每月步进为 1(这样不连续性会显示在纯连续的 ROW_NUMBER 上)。它还需要按照与ROW_NUMBER 相同的方式按员工进行分区。 @Steve - 更新...立即查看

以上是关于SQL Server:按月汇总,有间隔的主要内容,如果未能解决你的问题,请参考以下文章

如何在bigquery中按月/年汇总

linq 里按月查询汇总

按月汇总数据的分区行

使用汇总(或行总计)进行 SQL 透视

Python - 按月汇总并计算平均值

MySQL按月汇总并运行总计[重复]