可以统计和检查流程时间是否在轮班计划范围内的查询

问题描述 投票:0回答:1

我有2张桌子
第一张桌子有

startprocesstime
endprocesstime

第二张表有
EmployeeID
StartShift
EndShift

我需要检查

startprocesstime
Endprocesstime
是否仍在我的
shiftschedule
范围内。

示例:场景 1:开始进程时间

2023-11-18 4:30:000
结束进程时间
2023-11-18 4:31:000

场景 2:开始处理时间
2023-11-19 00:30:000
结束处理时间
2023-11-19 00:31:000

EmployeedID  4pm(StartShift) to 1am(EndShift).
sql sql-server count dateadd
1个回答
0
投票

一种方法是将流程与班次交叉连接,然后在每个流程涵盖的所有日期之间复制班次。请注意,如果该班次跨越午夜,则第一个候选班次可能会在流程开始的前一天开始。

然后可以使用标准测试

start1 < end2 AND start2 < end1
检查流程和班次日期/时间范围是否重叠。对于每次重叠,重叠量(以分钟为单位)可以计算为
DATEDIFF(minute, GREATEST(start1, start2), LEAST(end1, end2))

最后,由于多天内相同流程/班次组合可能会产生多个结果,因此可以使用

GROUP BY
将它们组合起来,并应用
SUM()
来总计计算出的重叠。

生成的查询类似于:

SELECT
    P.Name AS PName
    ,CONVERT(SMALLDATETIME, P.Start) AS PStart
    ,CONVERT(SMALLDATETIME, P.Finish) AS PFinish
    ,SUM(DATEDIFF(minute, GREATEST(P.Start, SS.Start), LEAST(P.Finish, SS.Finish))) AS Minutes
    ,S.Name AS SName
    ,CONVERT(CHAR(5), S.Start, 8) AS SStart
    ,CONVERT(CHAR(5), S.Finish, 8) AS SFinish
FROM (
    -- Process data plus some calculated fields
    SELECT
        P.*,
        CONVERT(DATE, P.Start) AS StartDate,
        DATEDIFF(day, P.Start, P.Finish) AS Days
    FROM Process P
) P
CROSS JOIN (
    -- Shift data plus a check for midnight crossover
    SELECT
        S.*,
        CASE WHEN S.Start > S.Finish THEN 1 ELSE 0 END AS CrossOver
    FROM Shift S
) S
CROSS APPLY (
    -- Replicate shifts across all dates covered by each process
    SELECT
        CONVERT(DATETIME, DATEADD(day, G.value, P.StartDate)) + CONVERT(DATETIME, S.Start) AS Start,
        CONVERT(DATETIME, DATEADD(day, G.value + S.Crossover, P.StartDate)) + CONVERT(DATETIME, S.Finish) AS Finish  
    FROM GENERATE_SERIES(-S.Crossover, P.Days) G
) SS
WHERE (P.Start < SS.Finish AND SS.Start < P.Finish) -- overlap test
GROUP BY
    P.Name, P.Start, P.Finish
    ,S.Name, S.Start, S.Finish
ORDER BY P.Name, S.Name

带有一些附加测试数据的示例结果:

P姓名 开始 P完成 分钟 S姓名 开始 S完成
流程1 2023-11-18 04:30 2023-11-18 04:31 1 班次2 23:00 07:00
流程2 2023-11-19 00:30 2023-11-19 00:31 1 班次1 16:00 01:00
流程2 2023-11-19 00:30 2023-11-19 00:31 1 班次2 23:00 07:00
流程3 2023-11-22 23:45 2023-11-23 00:15 30 班次1 16:00 01:00
流程3 2023-11-22 23:45 2023-11-23 00:15 30 班次2 23:00 07:00
流程4 2023-11-24 23:45 2023-11-27 00:15 1110 班次1 16:00 01:00
流程4 2023-11-24 23:45 2023-11-27 00:15 990 班次2 23:00 07:00
流程4 2023-11-24 23:45 2023-11-27 00:15 120 移3 01:00 02:00
流程4 2023-11-24 23:45 2023-11-27 00:15 1080 班次4 07:00 16:00
流程4 2023-11-24 23:45 2023-11-27 00:15 1080 转变5 12:00 21:00

参见这个数据库<>小提琴

我还尝试了一种不同的方法,其中班次和处理日期/时间范围在所有午夜交叉点都分开。虽然达到了相同的结果,但是代码更加复杂。我没有在这里发布该源代码,但已将其包含在上述小提琴的末尾。

© www.soinside.com 2019 - 2024. All rights reserved.