MSSQL 2008 слияние смежных дат с группировками


Я искал повсюду в течение нескольких недель, пытаясь найти решение своей проблемы.

Насколько я могу установить, моя версия SQL Server (2008r2)является ограничивающим фактором в этом, но я уверен, что есть решение.

Моя проблема заключается в следующем:

Есть таблица с потенциальными последовательные даты в форме поддержки-статус-DateStart-DateEnd-кодом.

Мне нужно объединить смежные даты по клиенту и статусу-поле статус может сдвинуться вверх и вниз по всему пути клиентов.

Некоторые примеры данных таковы:

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 2

1 ответ:

Попробуйте это

    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

Вывод

CusomerID   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