根据 SQL 中的持续时间和数量生成时间段
Generate time slots based on duration and quantity in SQL
我有一个 table 出于某种原因存储这样的循环:
Rota | Date_Start | Position | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+----------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 3 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 4 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 5 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 6 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 7 | 15 | 12 | Not available
372387412 | 2020-04-12 08:00:00.000 | 8 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 9 | 15 | 1 | Not available
更改 table 不是一个选项。
我生成了这个:
ID_Rota | Date_Start | RowNumber | Position | Number | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+-----------+----------+--------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 1 | 1 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2 | 1 | 2 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 3 | 1 | 3 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 4 | 1 | 4 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 5 | 1 | 5 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 6 | 1 | 6 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 7 | 1 | 7 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 8 | 1 | 8 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 9 | 1 | 9 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 10 | 1 | 10 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 11 | 1 | 11 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 12 | 1 | 12 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 13 | 1 | 13 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 14 | 1 | 14 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 15 | 1 | 15 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 16 | 2 | 1 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 17 | 3 | 1 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 18 | 4 | 1 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 19 | 4 | 2 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 20 | 4 | 3 | 15 | 13 | Not available
(前20行,共46行)
这是使用以下 SQL:
生成的
select
rs.ID_Rota,
rs.Date_Start,
row_number() over (partition by rs.Date_Start, rs.ID_Rota order by rs.Position, n.Number) as [RowNumber],
rs.Position,
n.Number,
rs.Duration,
rs.Quantity,
rs.Rota_Slot_Type
from dbo.RotaSlots as [rs]
cross apply
(
select top (rs.Quantity)
n.Number + 1 as [Number]
from dbo.Numbers as [n]
) as [n]
我遇到困难的部分是为每一行生成一个 Slot_Start 列。我的预期输出是:
ID_Rota | Date_Start | Slot_Start | RowNumber | Position | Number | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+-------------------------+-----------+----------+--------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:00:00.000 | 1 | 1 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:15:00.000 | 2 | 1 | 2 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:30:00.000 | 3 | 1 | 3 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:45:00.000 | 4 | 1 | 4 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:00:00.000 | 5 | 1 | 5 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:15:00.000 | 6 | 1 | 6 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:30:00.000 | 7 | 1 | 7 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:45:00.000 | 8 | 1 | 8 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:00:00.000 | 9 | 1 | 9 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:15:00.000 | 10 | 1 | 10 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:30:00.000 | 11 | 1 | 11 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:45:00.000 | 12 | 1 | 12 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:00:00.000 | 13 | 1 | 13 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:15:00.000 | 14 | 1 | 14 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:30:00.000 | 15 | 1 | 15 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:45:00.000 | 16 | 2 | 1 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:15:00.000 | 17 | 3 | 1 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:30:00.000 | 18 | 4 | 1 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:45:00.000 | 19 | 4 | 2 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 13:00:00.000 | 20 | 4 | 3 | 15 | 13 | Not available
第一个方块相对简单 - (RowNumber - 1) * Duration
给我位置 1 下所有行的 Slot_Start。当你将方块切换到位置 2、位置 3 等时,它会掉下来.
非常感谢任何帮助。
获得Slot_Start时间的最简单方法是
- 对行进行排序(与 RowNumber 相同)
- 对前面所有行的持续时间进行累计(运行 总计)
- 将此累计总和添加到 Start_Datetime
换句话说 - 不是计算 (rownumber - 1) * Duration
,而是计算前面所有相关行的持续时间总和。
您可以使用如下表达式来计算 Slot_Start
DATEADD(minute, SUM(Duration) OVER (PARTITION BY ID_Rota, Date_Start ORDER BY RowNumber) - Duration, Date_Start) AS Slot_Start
请注意,您可能需要将代码放入子查询或 CTE 中,以便计算 RowNumber,或者您可以将 ROW_NUMBER 表达式等合并到同一组计算中。
您也可以在 window 函数中明确使用 ROWS,除非您需要考虑第一行,例如
ISNULL(DATEADD(minute, SUM(Duration) OVER (PARTITION BY ID_Rota, Date_Start ORDER BY RowNumber ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), Date_Start), Date_Start) AS Slot_Start2
这里有一个 db<>fiddle,其中的数据与您上面的数据相似(我开始了一条路,然后才意识到您在做一些不同的事情;但是,持续时间的累计总和应该仍然有效)。
我有一个 table 出于某种原因存储这样的循环:
Rota | Date_Start | Position | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+----------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 3 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 4 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 5 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 6 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 7 | 15 | 12 | Not available
372387412 | 2020-04-12 08:00:00.000 | 8 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 9 | 15 | 1 | Not available
更改 table 不是一个选项。
我生成了这个:
ID_Rota | Date_Start | RowNumber | Position | Number | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+-----------+----------+--------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 1 | 1 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2 | 1 | 2 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 3 | 1 | 3 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 4 | 1 | 4 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 5 | 1 | 5 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 6 | 1 | 6 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 7 | 1 | 7 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 8 | 1 | 8 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 9 | 1 | 9 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 10 | 1 | 10 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 11 | 1 | 11 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 12 | 1 | 12 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 13 | 1 | 13 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 14 | 1 | 14 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 15 | 1 | 15 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 16 | 2 | 1 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 17 | 3 | 1 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 18 | 4 | 1 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 19 | 4 | 2 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 20 | 4 | 3 | 15 | 13 | Not available
(前20行,共46行) 这是使用以下 SQL:
生成的select
rs.ID_Rota,
rs.Date_Start,
row_number() over (partition by rs.Date_Start, rs.ID_Rota order by rs.Position, n.Number) as [RowNumber],
rs.Position,
n.Number,
rs.Duration,
rs.Quantity,
rs.Rota_Slot_Type
from dbo.RotaSlots as [rs]
cross apply
(
select top (rs.Quantity)
n.Number + 1 as [Number]
from dbo.Numbers as [n]
) as [n]
我遇到困难的部分是为每一行生成一个 Slot_Start 列。我的预期输出是:
ID_Rota | Date_Start | Slot_Start | RowNumber | Position | Number | Duration | Quantity | Rota_Slot_Type
----------+-------------------------+-------------------------+-----------+----------+--------+----------+----------+---------------
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:00:00.000 | 1 | 1 | 1 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:15:00.000 | 2 | 1 | 2 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:30:00.000 | 3 | 1 | 3 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 08:45:00.000 | 4 | 1 | 4 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:00:00.000 | 5 | 1 | 5 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:15:00.000 | 6 | 1 | 6 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:30:00.000 | 7 | 1 | 7 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 09:45:00.000 | 8 | 1 | 8 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:00:00.000 | 9 | 1 | 9 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:15:00.000 | 10 | 1 | 10 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:30:00.000 | 11 | 1 | 11 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 10:45:00.000 | 12 | 1 | 12 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:00:00.000 | 13 | 1 | 13 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:15:00.000 | 14 | 1 | 14 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:30:00.000 | 15 | 1 | 15 | 15 | 15 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 11:45:00.000 | 16 | 2 | 1 | 15 | 1 | Support Slot
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:15:00.000 | 17 | 3 | 1 | 30 | 1 | Lunch Break
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:30:00.000 | 18 | 4 | 1 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 12:45:00.000 | 19 | 4 | 2 | 15 | 13 | Not available
372387412 | 2020-04-12 08:00:00.000 | 2020-04-12 13:00:00.000 | 20 | 4 | 3 | 15 | 13 | Not available
第一个方块相对简单 - (RowNumber - 1) * Duration
给我位置 1 下所有行的 Slot_Start。当你将方块切换到位置 2、位置 3 等时,它会掉下来.
非常感谢任何帮助。
获得Slot_Start时间的最简单方法是
- 对行进行排序(与 RowNumber 相同)
- 对前面所有行的持续时间进行累计(运行 总计)
- 将此累计总和添加到 Start_Datetime
换句话说 - 不是计算 (rownumber - 1) * Duration
,而是计算前面所有相关行的持续时间总和。
您可以使用如下表达式来计算 Slot_Start
DATEADD(minute, SUM(Duration) OVER (PARTITION BY ID_Rota, Date_Start ORDER BY RowNumber) - Duration, Date_Start) AS Slot_Start
请注意,您可能需要将代码放入子查询或 CTE 中,以便计算 RowNumber,或者您可以将 ROW_NUMBER 表达式等合并到同一组计算中。
您也可以在 window 函数中明确使用 ROWS,除非您需要考虑第一行,例如
ISNULL(DATEADD(minute, SUM(Duration) OVER (PARTITION BY ID_Rota, Date_Start ORDER BY RowNumber ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), Date_Start), Date_Start) AS Slot_Start2
这里有一个 db<>fiddle,其中的数据与您上面的数据相似(我开始了一条路,然后才意识到您在做一些不同的事情;但是,持续时间的累计总和应该仍然有效)。