我如何获得预期输出:基于此原始数据的空闲时间?
原始数据
时间 | 超时 |
---|---|
2024-09-01 10:00:00 | 2024-09-01 11:00:00 |
2024-09-01 10:00:00 | 2024-09-01 12:00:00 |
2024-09-01 10:20:00 | 2024-09-01 13:00:00 |
2024-09-01 14:00:00 | 2024-09-01 15:00:00 |
2024-09-01 15:30:00 | 2024-09-01 16:00:00 |
预期产量
时间 | 超时 | 持续时间 | 空闲时间 |
---|---|---|---|
2024-09-01 10:00:00 | 2024-09-01 11:00:00 | 60分钟 | 0分钟 |
2024-09-01 10:00:00 | 2024-09-01 12:00:00 | 120分钟 | 0分钟 |
2024-09-01 10:20:00 | 2024-09-01 13:00:00 | 160分钟 | 0分钟 |
2024-09-01 14:00:00 | 2024-09-01 15:00:00 | 120分钟 | 60分钟 |
2024-09-01 15:30:00 | 2024-09-01 16:00:00 | 30分钟 | 30分钟 |
我达到了持续时间,但在空闲时间中挣扎 我写的查询:
select TimeIn,TimeOut, DATEDIFF(MINUTE, Timein, Timeout) as duration
from [test_idletime]
对于重叠的时间范围,您可能会遇到一些奇怪的重叠场景,其中最后一个
TimeOut
不是来自紧邻的前一行(按 TimeIn
排序)。考虑时间范围:09:00-10:30, 09:15-10:15, 09:30-10:00, 11:00-12:00
。最后一行计算出的IdleTime
应该是30分钟,而不是60分钟。
要处理此问题,您需要计算当前的
TimeIn
与之前的 MAX(TimeOut)
TimeIn
的 < current TimeIn
并进行比较。这可以使用适当约束的窗口函数来计算嵌套查询或CTE中的运行MAX(TimeOut)
,并在外部/最终查询中计算IdleTime
来完成。
计算出来的
SELECT
TimeIn, TimeOut,
DATEDIFF(MINUTE, TimeIn, TimeOut) as Duration,
GREATEST(0, DATEDIFF(MINUTE, MaxPriorTimeOut, TimeIn)) as IdleTime
FROM (
SELECT
*,
MAX(TimeOut) OVER(
ORDER BY TimeIn
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
)AS MaxPriorTimeOut
FROM Data
) T
ORDER BY TimeIn
GREATEST()
函数在 SQL Server 2022 及更高版本中可用。对于早期版本,您可以使用 CASE
表达式来获得相同的结果。
CASE WHEN MaxPriorTimeOut < TimeIn
THEN DATEDIFF(MINUTE, MaxPriorTimeOut, TimeIn)
ELSE 0 END as IdleTime
结果(带有一些额外的测试数据):
时间 | 超时 | 持续时间 | 空闲时间 |
---|---|---|---|
2024-09-01 10:00 | 2024-09-01 11:00 | 60 | 0 |
2024-09-01 10:00 | 2024-09-01 12:00 | 120 | 0 |
2024-09-01 10:20 | 2024-09-01 13:00 | 160 | 0 |
2024-09-01 14:00 | 2024-09-01 15:00 | 60 | 60 |
2024-09-01 15:30 | 2024-09-01 16:00 | 30 | 30 |
2024-09-02 09:00 | 2024-09-02 10:30 | 90 | 1020 |
2024-09-02 09:15 | 2024-09-02 10:15 | 60 | 0 |
2024-09-02 09:30 | 2024-09-02 10:00 | 30 | 0 |
2024-09-02 11:00 | 2024-09-02 12:00 | 60 | 30 |
请参阅 this db<>fiddle 进行演示。
嗯,我发现了一些东西,但可能可以更即兴创作,任何新的想法都是受欢迎的: 在此输入图片描述
选择 TimeIn、TimeOut、DATEDIFF(MINUTE、Timein、Timeout) 作为持续时间, DATEDIFF(MINUTE, TimeIn, lag(TimeOut) OVER (ORDER BY timeout asc)) < 0 then SUBSTRING(Convert(varchar, DATEDIFF(MINUTE, TimeIn, lag(TimeOut) OVER (ORDER BY timeout))) , 2, 100) -- value came as - to remove - added substing else '0' end as idletime FROM [test_idletime]