我有一个查询,它提供了有关传入工作的一般信息:
Start End ToPack
2016-04-07 10:00 14:00 40
2016-04-07 16:00 20:00 80
...
很容易计算,我必须每小时10到14个单位,每小时10到14个单位,每小时16到20个单位。我希望能够在这样的表格中展示它:
TIME ToPack
10:00 10
11:00 10
12:00 10
...
16:00 20
17:00 20
...
etc
我一直在尝试使用CTE,但到目前为止,我已经失败了......
答案 0 :(得分:3)
我使用table of numbers和CROSS APPLY
。
数字表只是一个表,其中一列的整数从1到足够大,例如100,000。我个人使用100K数字的表。 Aaron Bertrand写了一篇good article来解释如何生成这样的表格。
示例数据
DECLARE @T TABLE (StartDT datetime2(0), EndDT datetime2(0), ToPack float);
INSERT INTO @T (StartDT, EndDT, ToPack) VALUES
('2016-04-07 10:00:00', '2016-04-07 14:00:00', 40),
('2016-04-07 16:00:00', '2016-04-07 20:00:00', 80);
<强>查询强>
SELECT *
FROM
@T AS T
CROSS APPLY
(
SELECT
DATEADD(hour, dbo.Numbers.Number-1, T.StartDT) AS HourDT
, T.ToPack / DATEDIFF(hour, T.StartDT, T.EndDT) AS ToPackPerHour
FROM dbo.Numbers
WHERE dbo.Numbers.Number <= DATEDIFF(hour, T.StartDT, T.EndDT)
) AS CA
ORDER BY HourDT;
<强>结果强>
+---------------------+---------------------+--------+---------------------+---------------+
| StartDT | EndDT | ToPack | HourDT | ToPackPerHour |
+---------------------+---------------------+--------+---------------------+---------------+
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 | 40 | 2016-04-07 10:00:00 | 10 |
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 | 40 | 2016-04-07 11:00:00 | 10 |
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 | 40 | 2016-04-07 12:00:00 | 10 |
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 | 40 | 2016-04-07 13:00:00 | 10 |
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 | 80 | 2016-04-07 16:00:00 | 20 |
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 | 80 | 2016-04-07 17:00:00 | 20 |
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 | 80 | 2016-04-07 18:00:00 | 20 |
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 | 80 | 2016-04-07 19:00:00 | 20 |
+---------------------+---------------------+--------+---------------------+---------------+
答案 1 :(得分:0)
作为@ Vladimir优秀解决方案的变体,我可以使用非常方便的generate_series函数提出一个。
示例数据 (完全以文本格式使用您的数据):
CREATE TABLE #ToPack (StartDT char(16), EndT char(5), ToPack int);
INSERT INTO #ToPack VALUES ('2016-04-07 10:00', '14:00', 40);
INSERT INTO #ToPack VALUES ('2016-04-07 16:00', '20:00', 80);
查询 (建议的结果):
SELECT SUBSTRING(tp.StartDT, 1, 10) AS [Date],
SUBSTRING(CONVERT(varchar(20), s.date_hour, 120), 12, 5) AS TimeSlot,
s.ToPackSlot
FROM (
SELECT *, CONVERT(datetime, StartDT) AS date_start,
CONVERT(datetime, convert(char(11), StartDT)+EndT) AS date_end
FROM #ToPack
) tp
CROSS APPLY (
SELECT DATEADD(hour, g.IntValue, tp.date_start) AS date_hour,
tp.ToPack / DATEDIFF(hour, tp.date_start, tp.date_end) AS ToPackSlot
FROM generate_series(1, DATEDIFF(hour, tp.date_start, tp.date_end), 1) g) s