2016-07-29 3 views
2

Я искал высоко и низко в течение нескольких недель, пытаясь найти решение моей проблемы.MSSQL 2008 Слияние смежных дат с группировками

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

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

А имеют таблицу с потенциальными смежными датами в виде Клиент-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 

Любые идеи/код будет значительно получил.

Спасибо,

Dan

+0

заказ во входной таблице не будет то же самое, так как вы хотите, чтобы сохранить приказ ? – TheGameiswar

+0

Обновленный вопрос о включении столбца EventID, который может использоваться в операторе ORDER –

+0

Как вы выбираете этот '2016-01-13 | NULL'? – NEER

ответ

2

Попробуйте

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 
+0

Почти работает ... Отсутствует дата окончания NULL для клиентов 1 и DateEnds, похоже, уже не соприкасаются с DateStarts .. –

+0

Let я меняю его. – NEER

+0

Спасибо NEER - Его ближе, чем у меня! –