Sql-Server
連續日期範圍 - 差距和島嶼
CREATE TABLE T1 (Asset_Id int, Trailer_Id int, AssignStart datetime, AssignEnd DATETIME) ; INSERT INTO T1 (Asset_Id, Trailer_Id, AssignStart, AssignEnd) VALUES (37124, 32607, '2018-04-19 08:55:00', '2018-05-05 10:00:00.000'), (37124, 32607, '2018-05-05 11:23:00', NULL), (33000, 30000, '2018-04-01 15:00:00', '2018-04-15 10:30:00.000'), (34000, 31000, '2018-04-05 10:00:00', '2018-04-10 09:30:00.000'), (34000, 32500, '2018-04-10 09:31:00', NULL), (37000, 32600, '2018-04-19 08:55:00', '2018-04-25 08:30:00.000'), (37000, 32600, '2018-04-25 09:23:00', '2018-04-25 10:00:00.000'), (37000, 32600, '2018-04-25 11:23:00', '2018-04-30 15:00:00.000'), (37000, 32600, '2018-04-30 16:15:00', '2018-04-30 17:30:00.000'), (37000, 32600, '2018-05-01 18:23:00', NULL), (38000, 36000, '2018-05-01 10:00:00', '2018-05-10 06:30:00.000'), (38000, 36000, '2018-05-15 09:00:00', '2018-05-20 11:00:00.000'), (38000, 36000, '2018-05-20 12:00:00', NULL), (33000, 30000, '2018-05-01 10:00:00', NULL) ;
我有以下範例數據 -
Asset_Id Trailer_Id AssignStart AssignEnd 37124 32607 2018-04-19 08:55:00.000 2018-05-05 10:00:00.000 37124 32607 2018-05-05 11:23:00.000 NULL 33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000 34000 31000 2018-04-05 10:00:00.000 2018-04-10 09:30:00.000 34000 32500 2018-04-10 09:31:00.000 NULL 37000 32600 2018-04-19 08:55:00.000 2018-04-25 08:30:00.000 37000 32600 2018-04-25 09:23:00.000 2018-04-25 10:00:00.000 37000 32600 2018-04-25 11:23:00.000 2018-04-30 15:00:00.000 37000 32600 2018-04-30 16:15:00 2018-04-30 17:30:00.000 37000 32600 2018-05-01 18:23:00 NULL 38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000 38000 36000 2018-05-15 09:00:00.000 2018-05-20 11:00:00.000 38000 36000 2018-05-20 12:00:00.000 NULL 33000 30000 2018-05-01 10:00:00.000 NULL
如您所見,資產和預告片之間的一些分配在同一天結束並再次開始 - 除了最後一行 - 差距和島嶼
範例(1)
Asset_Id Trailer_Id AssignStart AssignEnd 37000 32600 2018-04-19 08:55:00.000 2018-04-25 08:30:00.000 37000 32600 2018-04-25 09:23:00.000 2018-04-25 10:00:00.000 37000 32600 2018-04-25 11:23:00.000 2018-04-30 15:00:00.000 37000 32600 2018-04-30 16:15:00.000 2018-04-30 17:30:00.000 37000 32600 2018-05-01 18:23:00.000 NULL
我期待的這個樣本的輸出是
Asset_Id Trailer_Id AssignStart AssignEnd 37000 32600 2018-04-19 08:55:00.000 2018-04-30 17:30:00.000 37000 32600 2018-05-01 18:23:00.000 NULL
現在這是另一部分與間隙和島嶼。相同資產和預告片之間的某些分配已結束,然後在將來的某個日期重新開始
範例(2)
Asset_Id Trailer_Id AssignStart AssignEnd 33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000 33000 30000 2018-05-01 10:00:00.000 NULL
我期待的這個樣本的輸出是
Asset_Id Trailer_Id AssignStart AssignEnd 33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000 33000 30000 2018-05-01 10:00:00.000 NULL
範例(3)
Asset_Id Trailer_Id AssignStart AssignEnd 38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000 38000 36000 2018-05-15 09:00:00.000 2018-05-20 11:00:00.000 38000 36000 2018-05-20 12:00:00.000 NULL
我期待的這個樣本的輸出是
Asset_Id Trailer_Id AssignStart AssignEnd 38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000 38000 36000 2018-05-15 09:00:00.000 NULL
我努力編寫將提供以下輸出的查詢
Asset_Id Trailer_Id AssignStart AssignEnd 37124 32607 2018-04-19 08:55:00.000 NULL 33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000 34000 31000 2018-04-05 10:00:00.000 2018-04-10 09:30:00.000 34000 32500 2018-04-10 09:31:00.000 NULL 37000 32600 2018-04-19 08:55:00.000 2018-04-30 17:30:00.000 37000 32600 2018-05-01 18:23:00.000 NULL 38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000 38000 36000 2018-05-15 09:00:00.000 NULL 33000 30000 2018-05-01 10:00:00.000 NULL
您可以在 CTE 的幫助下使用遞歸方法。為此,我添加了一個
Row_Number
so ,以確保它是驗證的下一條記錄。然後創建遞歸 CTE…命名
cte
。在這裡,欄位很重要rn as rn_init
——這是創建記錄鏈的基礎。; WITH fr AS -- first records ( SELECT [Asset_Id], [Trailer_Id], [AssignStart], [AssignEnd] ,ROW_NUMBER()OVER( PARTITION BY [Asset_Id], [Trailer_Id] ORDER BY [AssignStart], [AssignEnd]) AS rn FROM T1 ) ,cte AS ( SELECT [Asset_Id], [Trailer_Id] , [AssignStart] as [AssignStart_init] , [AssignEnd] as [AssignEnd_Init] , [AssignStart] as [AssignStart], [AssignEnd] as [AssignEnd] , 0 as lvl , rn as rn , rn as rn_init FROM fr --WHERE [AssignEnd] is not null UNION ALL SELECT T1.[Asset_Id], T1.[Trailer_Id] ,C.[AssignStart_init],C.[AssignEnd_Init] ,T1.[AssignStart], T1.[AssignEnd] ,C.lvl + 1 ,T1.rn ,C.rn_init FROM fr AS T1 INNER JOIN cte as C ON T1.[Asset_Id] = C.[Asset_Id] AND T1.[Trailer_Id] = C.[Trailer_Id] AND CONVERT(DATE,C.[AssignEnd]) = CONVERT(DATE,T1.[AssignStart]) AND C.[AssignEnd] <= T1.[AssignStart] AND C.rn + 1 = T1.rn )
這里處理
NULL
的是 AssignEnd 的情況,也很重要,要計算“記錄鏈”count(rn_init) as c_rn_init
。基於此,稍後對其進行過濾。--select * from cte ,myPrecious AS ( select --C.* C.[Asset_Id],c.[Trailer_Id] ,MIN([AssignStart]) as AssignStart --,MAX([AssignEnd]) as AssignEnd ,CASE WHEN MAX(isnull([AssignEnd],[AssignStart])) = MAX([AssignStart]) THEN NULL ELSE MAX(isnull([AssignEnd],[AssignStart])) END as [AssignEnd] ,count(rn_init) as c_rn_init from cte as c group by C.[Asset_Id],c.[Trailer_Id], C.rn_init )
這如果最終查詢。添加了 Row_number ,所以要過濾掉記錄,
ORDER BY c_rn_init DESC
SELECT Asset_Id,Trailer_Id,AssignStart,AssignEnd --,c_rn_init --,rn FROM( SELECT * ,row_number() OVER(PARTITION BY [Asset_Id],[Trailer_Id] , AssignEnd ORDER BY c_rn_init DESC) as rn FROM myPrecious )A WHERE A.rn = 1 order by [Asset_Id],[Trailer_Id] ,[AssignStart],[AssignEnd]
輸出:
Asset_Id Trailer_Id AssignStart AssignEnd 33000 30000 01/04/2018 15:00:00 15/04/2018 10:30:00 33000 30000 01/05/2018 10:00:00 null 34000 31000 05/04/2018 10:00:00 10/04/2018 09:30:00 34000 32500 10/04/2018 09:31:00 null 37000 32600 19/04/2018 08:55:00 30/04/2018 17:30:00 37000 32600 01/05/2018 18:23:00 null 37124 32607 19/04/2018 08:55:00 null 38000 36000 01/05/2018 10:00:00 10/05/2018 06:30:00 38000 36000 15/05/2018 09:00:00 null