MSSQL 2008使用分组合并连续日期

时间:2016-07-29 10:02:23

标签: sql-server tsql sql-server-2008-r2

我已经搜索了好几个星期,现在试图找到解决问题的方法。

据我所知,我的SQL Server版本(2008r2)是一个限制因素,但我很肯定有一个解决方案。

我的问题如下:

A以Customer-Status-DateStart-DateEnd-EventID的形式拥有一个具有潜在连续日期的表。

我需要按客户和状态合并连续日期 - 状态字段可以在客户途径中上下移动。

一些示例数据如下:

DECLARE @Tbl TABLE([CustomerID] INT
              ,[Status] INT
              ,[DateStart] DATE
              ,[DateEnd] DATE
              ,[EventID] INT)                 

INSERT INTO @Tbl
VALUES (1,1,'20160101','20160104',1)
      ,(1,1,'20160104','20160108',3)
      ,(1,2,'20160108','20160110',4)
      ,(1,1,'20160110','20160113',7)
      ,(1,3,'20160113','20160113',9)
      ,(1,3,'20160113',NULL,10)
      ,(2,1,'20160101',NULL,2)
      ,(3,2,'20160109','20160110',5)
      ,(3,1,'20160110','20160112',6)
      ,(3,1,'20160112','20160114',8)

期望的输出:

Customer | Status | DateStart | DateEnd
---------+--------+-----------+-----------
1        |  1     | 2016-01-01| 2016-01-08
1        |  2     | 2016-01-08| 2016-01-10
1        |  1     | 2016-01-10| 2016-01-13
1        |  3     | 2016-01-13| NULL
2        |  1     | 2016-01-01| NULL
3        |  2     | 2016-01-09| 2016-01-10
3        |  1     | 2016-01-10| 2016-01-14

任何想法/代码都将受到极大的欢迎。

谢谢,

1 个答案:

答案 0 :(得分:2)

试试这个

final

输出

    DECLARE @Tbl TABLE([CusomerID] INT
              ,[Status] INT
              ,[DateStart] DATE
              ,[DateEnd] DATE
              ,[EventID] INT)                 

INSERT INTO @Tbl
VALUES (1,1,'20160101','20160104',1)
      ,(1,1,'20160104','20160108',3)
      ,(1,2,'20160108','20160110',4)
      ,(1,1,'20160110','20160113',7)
      ,(1,3,'20160113','20160113',9)
      ,(1,3,'20160113',NULL,10)
      ,(2,1,'20160101',NULL,2)
      ,(3,2,'20160109','20160110',5)
      ,(3,1,'20160110','20160112',6)
      ,(3,1,'20160112','20160114',8)



;WITH CTE
AS
(
  SELECT CusomerID ,
         Status ,
         DateStart ,
         COALESCE(DateEnd, '9999-01-01') AS DateEnd,
         EventID, 
         ROW_NUMBER() OVER (ORDER BY CusomerID, EventID) RowId,  
         ROW_NUMBER() OVER (PARTITION BY CusomerID, Status ORDER BY EventID) StatusRowId FROM @Tbl
)

SELECT
    A.CusomerID ,
    A.Status ,
    A.DateStart ,
    CASE WHEN A.DateEnd = '9999-01-01' THEN NULL
    ELSE A.DateEnd END AS DateEnd
FROM
(
    SELECT 
        CTE.CusomerID, 
        CTE.Status,
        MIN(CTE.DateStart) AS DateStart,
        MAX(CTE.DateEnd) AS DateEnd
    FROM 
        CTE
    GROUP BY 
        CTE.CusomerID, 
        CTE.Status,
        CTE.StatusRowId -CTE.RowId      
) A
ORDER BY A.CusomerID, A.DateStart