如何使用T-SQL将行标记为长期病?

问题描述

我面临挑战。我们的业务想知道员工的病假是否是长期的。因此,如果疾病是连续30天的一部分,则所有30条或更多记录都应标记为[长期疾病] =真

病假只有星期一-星期五

我有一张桌子,每个员工患病的每个日历日都有一行,如下所示:

enter image description here

这甚至可以用T-sql解决吗?

解决方法

所以这是一个简单的解决方案。

我在每个日历日(s或w)生成一张病假或病假的表格

然后,我将过去30个日历日(不包括周末)中每天没有病的日子都计算在内。

如果这段时间里有0井日,那么它就是长期病,因此我们每天展望29天,看看是否在接下来的30天内隐藏了长期病。 如果这是一个有病的日子,并且在接下来的29天内,我们将隐藏一段无病的日子,那么这个有病的日子就是长期疾病的一部分。

在我的示例中,第二周是一个有病的一周,没有标记,四月甚至可能有病,几个月都标记为长期

WITH dates AS /* Generate som dates */
(
    SELECT CAST(DATEADD(DAY,ROW_NUMBER() OVER (ORDER BY (SELECT 1 n))-1,'2020-01-01') AS DATE) dato
    FROM (VALUES (0),(1),(2),(3),(4)) a (b),(VALUES (0),(4)) b (b),(4)) c (b)
),CTE AS /* Set 2nd week and 3,4 month as sick */
(
    SELECT IIF(MONTH(dato) IN (3,4) OR DATEPART(WEEK,dato) = 2,'s','w') state,dato
    FROM dates
),sums AS /* count days of work last 30 days current day included */
(
    SELECT dato,State,SUM(IIF(State = 'w' AND DATEPART(WEEKDAY,dato) NOT IN (1,7),1,0)) OVER (ORDER BY dato ROWS BETWEEN 29 PRECEDING AND CURRENT ROW) NonSickDays
    FROM CTE
),periods AS /* Check if no well days for any day in the next 30 days,current day included */
(
    SELECT dato,MIN(NonSickDays) OVER (ORDER BY dato ROWS BETWEEN CURRENT ROW AND 29 FOLLOWING) Minperiod,NonSickDays
    FROM sums
)
SELECT dato /* id sick day,and minimum well days is 0 then its a long term day */,IIF(State = 's' AND Minperiod = 0,'l','') longtimesick,NonSickDays
FROM periods