【发布时间】:2021-05-14 14:20:45
【问题描述】:
我再次发布this question,因为项目发生了变化,并且之前的答案没有返回预期的结果。救护车和消防车有紧急情况发生时的调度时间和宣布紧急情况结束时的结束时间。
活动 1 于 2021 年 5 月 1 日 10:17:33 开始,并于 2021 年 5 月 1 日 10:33:41 结束。
活动 2 于 2021 年 5 月 1 日 11:50:52 开始,并于 2021 年 5 月 1 日 13:18:21 结束。
我想解析从开始到结束的时间量,并在它发生时将其放入小时部分。例如;活动 1 开始于 10:17,结束于 10:33。它将在当天的 10:00 小时部分放置 16 分钟。事件 2 将在 11:00 小时部分放置 10 分钟,在 12:00 小时部分放置 60 分钟,在 13:00 小时部分放置 18 分钟。将分钟放在事件发生的小时数中。
结果应如下所示。虽然我很灵活。例如,如果卡车的名称不能在结果中返回,那也没关系,因为如果 EventID 在那里,我可以关联回原始表。
| EventID | Ambulance | EventDayOfYear | EventHour | MinutesAllocated |
|---|---|---|---|---|
| 1 | Medic10 | 121 | 10 | 16 |
| 1 | Medic10 | 121 | 11 | 10 |
| 2 | Ladder73 | 121 | 11 | 10 |
| 2 | Ladder73 | 121 | 12 | 60 |
| 2 | Ladder73 | 121 | 13 | 18 |
| 3 | Engine41 | 121 | 13 | 33 |
| 3 | Engine41 | 121 | 14 | 21 |
| 4 | Medic83 | 121 | 15 | 32 |
| 4 | Medic83 | 121 | 16 | 5 |
| 5 | Rescue32 | 121 | 16 | 33 |
| 6 | Medic09 | 121 | 23 | 16 |
| 6 | Medic09 | 122 | 0 | 39 |
| 7 | Engine18 | 121 | 23 | 28 |
| 7 | Engine18 | 122 | 0 | 60 |
| 7 | Engine18 | 122 | 1 | 34 |
| 8 | Rescue63 | 122 | 0 | 35 |
以下 SQL 代码接近于提供正确的结果。 但不重叠天数。有许多紧急事件从 2300 时开始,一直持续到第二天 0300 时。
DECLARE @tempFireEvents TABLE
(
EventID INT NOT NULL
, Apparatus VARCHAR(10) NOT NULL
, StartDateTime DATETIME NOT NULL
, EndDateTime DATETIME NOT NULL
, DurationInSeconds INT NOT NULL
)
INSERT INTO @tempFireEvents
VALUES
(1, 'Medic10', 'may 1, 2021 10:17:33', 'may 1, 2021 10:33:41', 968) /*This event is entirely within 1000 hours*/
, (2, 'Ladder73', 'may 1, 2021 11:50:52', 'may 1, 2021 13:18:21', 5249) /*This event spans 1100, 1200 and 1300 hours*/
, (3, 'Engine41', 'may 1, 2021 13:27:17', 'may 1, 2021 14:21:18', 3241) /*This event overlaps 1300 and 1400 hours*/
, (4, 'Medic83', 'may 1, 2021 15:28:08', 'may 1, 2021 16:05:48', 2260) /*This event overlaps 1500 and 1600 hours*/
, (5, 'Rescue32', 'may 1, 2021 16:20:43', 'may 1, 2021 16:53:28', 1965) /*This event is entirely within the 1600 hour part*/
, (6, 'Medic09', 'may 1, 2021 23:44:06', 'may 2, 2021 00:39:52', 3346) /*Notice this overlaps the 2300 and 0000 hours into the following day*/
, (7, 'Engine18', 'may 1, 2021 23:32:58', 'may 2, 2021 01:34:13', 7275) /*Notice this overlaps the 2300, 0000 and 0100 hours into the following day*/
, (8, 'Rescue63', 'may 2, 2021 00:17:45', 'may 2, 2021 00:52:09', 2064) /*Notice this is the 00 hour of the day and does not show in the results*/
;
WITH AllHours AS
(
SELECT 1 AS hourInt
UNION ALL
SELECT hourInt + 1
FROM AllHours
WHERE hourInt < 23
)
,
Combined AS
(
SELECT
T.EventID
, H.hourInt
, CASE WHEN DATEPART(HOUR, T.StartDateTime) = H.hourInt THEN 1 ELSE 0 END AS isStart
, CASE WHEN DATEPART(HOUR, T.EndDateTime) = H.hourInt THEN 1 ELSE 0 END AS isEnd
, T.StartDateTime
, T.EndDateTime
FROM @tempFireEvents AS [T]
JOIN AllHours AS [H] ON H.hourInt BETWEEN DATEPART(HOUR, T.StartDateTime) AND DATEPART(HOUR,T.EndDateTime)
)
SELECT
EventID
, hourInt
, CASE WHEN isStart = 1 AND isEnd = 0 THEN 60 - DATEPART(MINUTE, StartDateTime)
WHEN isStart = 0 AND isEnd = 1 THEN DATEPART(MINUTE, EndDateTime)
WHEN isStart = 1 AND isEnd = 1 THEN DATEPART(MINUTE, EndDateTime) - DATEPART(MINUTE, StartDateTime)
ELSE 60
END AS MinutesInThisHour
FROM Combined
ORDER BY EventID ASC, hourint ASC
;
我怀疑 SQL Server 可能不是实现目标的最佳方法。它可能需要用 Python 编写,带有增量和减量以及计数器。
如果有帮助,我有一个看起来像这样的日历表:
May 1, 2021 00:00:00
May 1, 2021 01:00:00
May 1, 2021 02:00:00
May 1, 2021 03:00:00
May 1, 2021 04:00:00
May 1, 2021 05:00:00
May 1, 2021 06:00:00
日历表对解决这个问题有用吗?
【问题讨论】:
-
请不要使用 HTML 来回答您的问题。
<body>标签之类的东西破坏了降价。 -
您的结束声明“我有一个如下所示的日历表:” 意味着您的日历表将日期存储为
varchar。如果是这样,那么恐怕那个日历表就没有用了。有日期和时间数据类型是有原因的。 -
当我写这个问题时,Stack Overflow 有一条错误消息:它不会在没有正文标签的情况下发布。当我放入 标记时,错误消息消失了。其次,日期时间值作为 DATETIME 存储在 SQL Server 中。
-
AllHours 不应该返回 0..23 吗?另外,为什么是递归 CTE?为什么不
with AllHours as (select * from (values (0), (1), ... , (23)) H(HourInt) )甚至是理货表? -
AlwaysLearning:您提出的解决方案不能解决事件 6 和 7 重叠天的问题。事件 6 从 2300 时开始,在 00:00 时结束。事件 7 从 2300 开始,一直持续到 00:00,并在 01:00 结束。我要解决的问题是如何编写代码来处理重叠天数的事件。谢谢。
标签: sql-server python-3.x temporal