![](/img/trans.png)
[英]How to split a date range in a row into time spent in each hour in a day in SQL
[英]Split Date/Time Data by Hour and Expand a Range of Date/Time into Rows
我正在尝试使用 SQL Server 将一系列日期/时间数据扩展为多行。 例如,我的数据看起来像
Date StartTime EndTime EmployeeID ShiftType
10/1/2019 8:30:00AM 4:57:00PM 52148 Shift
10/2/2019 9:00:00AM 5:24:00PM 72156 Shift
10/2/2019 8:27:00AM 4:40:00PM 59232 Shift
我想按小时将日期和时间范围扩展为多行。 它看起来像:
Date StartTime EndTime EmployeeID ShiftType
10/1/2019 8:30:00AM 9:00:00PM 52148 Shift
10/1/2019 9:00:00AM 10:00:00PM 52148 Shift
10/1/2019 10:00:00AM 11:00:00PM 52148 Shift
10/1/2019 11:00:00AM 12:00:00PM 52148 Shift
10/1/2019 12:00:00AM 1:00:00PM 52148 Shift
10/1/2019 1:00:00AM 2:00:00PM 52148 Shift
10/1/2019 2:00:00AM 3:00:00PM 52148 Shift
10/1/2019 3:00:00AM 4:00:00PM 52148 Shift
10/1/2019 4:30:00AM 4:57:00PM 52148 Shift
10/2/2019 9:00:00AM 10:00:00PM 72156 Shift
10/2/2019 10:00:00AM 11:00:00PM 72156 Shift
.......
如果开始时间是 8:20,我想在前 40 分钟单独排成一行,所以它可能是 8:20 -9:00 然后是 9:00-10:同样的事情适用于结束时间。 我厌倦了这样的事情,但显然它不起作用,因为我想以小时为单位拆分它们。
Declare @StartDate DATETIME = '2016-09-26 00:00:00.000';
With SampleDateTable AS
(
SELECT @StartDate AS myDate
UNION ALL
SELECT DATEADD(Day,1,myDate)
FROM Sheet1$
WHERE DATEADD(Day,1,myDate) <= GETDATE()
)
SELECT
EmployeeID,
a.myDate,
FROM SampleDateTable a
INNER JOIN
(
SELECT EmployeeID, MIN(StartTime) MinStartTime
FROM Sheet1$
GROUP BY EmployeeID
) EachEmployee ON
a.MyDate >= EachEmployee.MinStartTime
LEFT JOIN
Sheet1$ S ON
EachEmployee.EmployeeID = S.EmployeeID AND
a.myDate >= S.StartDate AND
a.myDate <= ISNULL(S.EndDate, GETDATE())
ORDER BY EachEmployee.EmployeeID DESC, a.MyDate
OPTION (MAXRECURSION 0)
我很感激这方面的任何帮助。 谢谢。
这是使用临时计数表的一种选择
例子
Declare @YourTable Table ([Date] date,[StartTime] time,[EndTime] time,[EmployeeID] int,[ShiftType] varchar(50))
Insert Into @YourTable Values
('10/1/2019','8:30:00AM','4:57:00PM',52148,'Shift')
,('10/2/2019','9:00:00AM','5:24:00PM',72156,'Shift')
,('10/2/2019','8:27:00AM','4:40:00PM',59232,'Shift')
Select Date
,StartTime = case when N=datepart(hour,StartTime) then StartTime else TimeFromParts(N,0,0,0,0) end
,EndTime = case when N=datepart(hour,EndTime) then EndTime else TimeFromParts(N+1,0,0,0,0) end
,EmployeeID
,ShiftType
From @YourTable A
Join ( values (0),(1),(2),(3),(4),(5),(6)
,(7),(8),(9),(10),(11),(12),(13)
,(14),(15),(16),(17),(18),(19),(20)
,(21),(22),(23)
) B(N)
on N between datepart(hour,StartTime) and datepart(hour,EndTime)
退货
Date StartTime EndTime EmployeeID ShiftType
2019-10-01 08:30:00.0000000 09:00:00.0000000 52148 Shift
2019-10-01 09:00:00.0000000 10:00:00.0000000 52148 Shift
2019-10-01 10:00:00.0000000 11:00:00.0000000 52148 Shift
2019-10-01 11:00:00.0000000 12:00:00.0000000 52148 Shift
2019-10-01 12:00:00.0000000 13:00:00.0000000 52148 Shift
2019-10-01 13:00:00.0000000 14:00:00.0000000 52148 Shift
2019-10-01 14:00:00.0000000 15:00:00.0000000 52148 Shift
2019-10-01 15:00:00.0000000 16:00:00.0000000 52148 Shift
2019-10-01 16:00:00.0000000 16:57:00.0000000 52148 Shift
2019-10-02 09:00:00.0000000 10:00:00.0000000 72156 Shift
2019-10-02 10:00:00.0000000 11:00:00.0000000 72156 Shift
2019-10-02 11:00:00.0000000 12:00:00.0000000 72156 Shift
2019-10-02 12:00:00.0000000 13:00:00.0000000 72156 Shift
2019-10-02 13:00:00.0000000 14:00:00.0000000 72156 Shift
2019-10-02 14:00:00.0000000 15:00:00.0000000 72156 Shift
2019-10-02 15:00:00.0000000 16:00:00.0000000 72156 Shift
2019-10-02 16:00:00.0000000 17:00:00.0000000 72156 Shift
2019-10-02 17:00:00.0000000 17:24:00.0000000 72156 Shift
2019-10-02 08:27:00.0000000 09:00:00.0000000 59232 Shift
2019-10-02 09:00:00.0000000 10:00:00.0000000 59232 Shift
2019-10-02 10:00:00.0000000 11:00:00.0000000 59232 Shift
2019-10-02 11:00:00.0000000 12:00:00.0000000 59232 Shift
2019-10-02 12:00:00.0000000 13:00:00.0000000 59232 Shift
2019-10-02 13:00:00.0000000 14:00:00.0000000 59232 Shift
2019-10-02 14:00:00.0000000 15:00:00.0000000 59232 Shift
2019-10-02 15:00:00.0000000 16:00:00.0000000 59232 Shift
2019-10-02 16:00:00.0000000 16:40:00.0000000 59232 Shift
对于递归查询,您应该从示例数据开始,然后从那里调整它。
在递归查询中,我们添加了一个额外的列:下一小时边界,又名NextTime
。 例如,对于StartTime
8:27,下一小时的边界是 9:00。 递归时,我们将其用作下一个StartTime
,然后EndTime
,直到到达EndTime
。
在结果查询中,我们隐藏NextTime
列,但选择NextTime
和EndTime
较早的作为该结果行的EndTime
。 由于递归不能以良好的顺序提供数据,我们还需要按StartTime
排序。
WITH hourly AS (
SELECT Date, EmployeeID, ShiftType, EndTime, StartTime
, TIMEFROMPARTS(DATEPART(hh, StartTime) + 1,
0, 0, 0, 0 ) AS NextTime
FROM SampleDateTable
UNION ALL
SELECT Date, EmployeeID, ShiftType, EndTime, NextTime
, TIMEFROMPARTS(DATEPART(hh, NextTime) + 1,
0, 0, 0, 0 ) AS NextTime
FROM hourly
WHERE NextTime < EndTime
)
SELECT Date, StartTime
, CASE WHEN NextTime < EndTime THEN NextTime ELSE EndTime END AS EndTime
, EmployeeID, ShiftType
FROM hourly
ORDER BY Date, EmployeeID DESC, StartTime
有关工作示例,请参阅SQL Fiddle 。
架构
CREATE TABLE SampleDateTable (
Date date NOT NULL,
StartTime time(0) NOT NULL,
EndTime time(0) NOT NULL,
EmployeeID int NOT NULL,
ShiftType varchar(10) NOT NULL
);
INSERT INTO SampleDateTable VALUES
( '10/1/2019', '8:30:00AM', '4:57:00PM', 52148, 'Shift' ),
( '10/2/2019', '9:00:00AM', '5:24:00PM', 72156, 'Shift' ),
( '10/2/2019', '8:27:00AM', '4:40:00PM', 59232, 'Shift' );
输出
Date StartTime EndTime EmployeeID ShiftType
2019-10-01 08:30:00 09:00:00 52148 Shift
2019-10-01 09:00:00 10:00:00 52148 Shift
2019-10-01 10:00:00 11:00:00 52148 Shift
2019-10-01 11:00:00 12:00:00 52148 Shift
2019-10-01 12:00:00 13:00:00 52148 Shift
2019-10-01 13:00:00 14:00:00 52148 Shift
2019-10-01 14:00:00 15:00:00 52148 Shift
2019-10-01 15:00:00 16:00:00 52148 Shift
2019-10-01 16:00:00 16:57:00 52148 Shift
2019-10-02 09:00:00 10:00:00 72156 Shift
2019-10-02 10:00:00 11:00:00 72156 Shift
2019-10-02 11:00:00 12:00:00 72156 Shift
2019-10-02 12:00:00 13:00:00 72156 Shift
2019-10-02 13:00:00 14:00:00 72156 Shift
2019-10-02 14:00:00 15:00:00 72156 Shift
2019-10-02 15:00:00 16:00:00 72156 Shift
2019-10-02 16:00:00 17:00:00 72156 Shift
2019-10-02 17:00:00 17:24:00 72156 Shift
2019-10-02 08:27:00 09:00:00 59232 Shift
2019-10-02 09:00:00 10:00:00 59232 Shift
2019-10-02 10:00:00 11:00:00 59232 Shift
2019-10-02 11:00:00 12:00:00 59232 Shift
2019-10-02 12:00:00 13:00:00 59232 Shift
2019-10-02 13:00:00 14:00:00 59232 Shift
2019-10-02 14:00:00 15:00:00 59232 Shift
2019-10-02 15:00:00 16:00:00 59232 Shift
2019-10-02 16:00:00 16:40:00 59232 Shift
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.