根据 SQL Server 中的日期和时间将单行拆分为多行



我想根据时间将一行分成多行。 下面是示例。

SrNo    Notification    StartDate                  EndDate
---------------------------------------------------------------------------
1       001003741915    2018-08-20 07:27:00.000    2018-08-21 16:23:00.000
2       001003779670    2018-08-21 03:36:00.000    2018-08-21 04:36:00.000
3       001003779830    2018-08-21 04:36:00.000    2018-08-21 21:35:00.000

预期输出如下:

SrNo    Notification    StartDate                  EndDate
---------------------------------------------------------------------------
1       001003741915    2018-08-20 07:27:00.000    2018-08-21 05:59:00.000
1       001003741915    2018-08-21 06:00:00.000    2018-08-21 16:23:00.000
2       001003779670    2018-08-21 03:36:00.000    2018-08-21 04:36:00.000
3       001003779830    2018-08-21 04:36:00.000    2018-08-21 05:59:00.000
3       001003779830    2018-08-21 06:00:00.000    2018-08-21 21:35:00.000

一天从06:00AM开始到第二天06:00 AM。当结束日期时间超过上午 06:00 时,将此日期拆分为两行。第一行结束日期为 2018-08-21 05:59:00.000,下一行开始日期为 2018-08-21 06:00:00.000。

下面的查询将为您提供帮助。

CREATE TABLE #test
(
Notifications varchar(50)
,StartDate datetime
,EndDate Datetime
,Id int
)
INSERT into #test
select              '001003741915','2018-08-20 07:27:00.000','2018-08-21 16:23:00.000',1
UNION select        '001003779670','2018-08-21 03:36:00.000','2018-08-21 04:36:00.000',2
UNION select        '001003779830','2018-08-21 04:36:00.000','2018-08-21 21:35:00.000',3
UNION select        '001003779835','2018-08-21 04:36:00.000','2018-08-24 21:35:00.000',4
;with cte
As (  SELECT 
ID,Notifications,StartDate,dateadd(d, datediff(d, 1, StartDate+1), '06:00') as StartOfDay, EndDate,dateadd(d, datediff(d, 1, EndDate+1), '06:00')  as EndDayOfDate
FROM #test
)
, Result
AS (

select Id
,Notifications
,StartDate 
,CASE WHEN StartOfDay BETWEEN StartDate AND EndDate THEN  StartOfDay
WHEN ENDDate <StartOfDay THEN ENDDate
WHEN ENDDate <EndDayOfDate THEN ENDDate
ELSE  EndDayOfDate  END AS  EndDate 
from cte
union ALL
Select T.Id
,T.Notifications
,R.EndDate As StartDate
,CASE WHEN R.EndDate+1 < T.EndDate THEN R.EndDate+1 ELSE  T.EndDate   END AS EndDate 
from cte  T
INNER JOIN Result R
ON R.Notifications=T.Notifications
WHERE  R.EndDate <T.EndDate
)
SELECT * FROM Result order by id

您可以通过使用递归 CTE 来实现此目的

WITH CTE AS (
SELECT ID, Notification, StartDate, EndDate 
FROM TAB1
UNION ALL
SELECT ID, Notification, DATEADD(DD,1,StartDate), EndDate 
FROM CTE
WHERE cast(StartDate as date) < cast(EndDate as date)
)
SELECT * FROM CTE order by id

如果开始日期和结束日期之间只有一天或更短的差异

如果我们称您的表 t1:

SELECT [SrNo]
,[Notification]
,[StartDate]
,[EndDate]
FROM [t1]
where DATEADD(MINUTE, 59,   DATEADD(HOUR, 5, CAST(CAST(enddate AS DATE) AS DATETIME))) > enddate
union 
SELECT [SrNo]
,[Notification]
,[StartDate]
,DATEADD(MINUTE, 59,   DATEADD(HOUR, 5, CAST(CAST(enddate AS DATE) AS DATETIME))) [EndDate]
FROM [t1]
where DATEADD(MINUTE, 59,   DATEADD(HOUR, 5, CAST(CAST(enddate AS DATE) AS DATETIME))) between startdate and enddate
union 
SELECT [SrNo]
,[Notification]
,DATEADD(MINUTE, 00,   DATEADD(HOUR, 6, CAST(CAST(enddate AS DATE) AS DATETIME))) [StartDate]
, [EndDate]
FROM [t1]
where DATEADD(MINUTE, 59,   DATEADD(HOUR, 5, CAST(CAST(enddate AS DATE) AS DATETIME))) between startdate and enddate
order by srno
,enddate 

基于 Nitika 的答案,我能够在 MySQL 中做到这一点并解决类似的问题:

WITH RECURSIVE CTE (id, name, start_dt, end_dt) AS (
SELECT id, name, cast(start_date as date) as start_dt, cast(end_date as date) as end_dt FROM event e1
UNION ALL
SELECT e2.id, e2.name, DATE_ADD(e2.start_dt, INTERVAL 1 DAY) as start_dt, e2.end_dt
FROM CTE e2
WHERE e2.start_dt < e2.end_dt
)
SELECT * FROM CTE order by start_dt

最新更新