根据开始和结束时间以及每小时的价值创建时间计划

时间:2016-04-07 03:15:46

标签: sql sql-server tsql sql-server-2012

我有一个查询,它提供了有关传入工作的一般信息:

  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,但到目前为止,我已经失败了......

2 个答案:

答案 0 :(得分:3)

我使用table of numbersCROSS 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