如何使用 T-SQL 将行标记为长期疾病?
How do I mark rows as longterm illness using T-SQL?
我有一个挑战。我们的企业想知道员工病假是否是长期病假。因此,如果疾病是 30 个并发日的一部分,则所有 30 个或更多记录应标记为 [long term illness] = True
病假只有周一到周五
我有一个 table,每个员工在他们生病的每个日历日都有一行,如下所示:
这甚至可以用 T-SQL 解决吗?
所以这是一个简单的解决方案。
我为每个日历日(s 或 w)生成一个 table 生病或健康
然后我计算过去 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), (1), (2), (3), (4)) b (b)
, (VALUES (0), (1), (2), (3), (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
, State
, 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 */
, State
, IIF(State = 's' AND Minperiod = 0, 'l', '') longtimesick
, NonSickDays
FROM periods
我有一个挑战。我们的企业想知道员工病假是否是长期病假。因此,如果疾病是 30 个并发日的一部分,则所有 30 个或更多记录应标记为 [long term illness] = True
病假只有周一到周五
我有一个 table,每个员工在他们生病的每个日历日都有一行,如下所示:
这甚至可以用 T-SQL 解决吗?
所以这是一个简单的解决方案。
我为每个日历日(s 或 w)生成一个 table 生病或健康
然后我计算过去 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), (1), (2), (3), (4)) b (b)
, (VALUES (0), (1), (2), (3), (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
, State
, 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 */
, State
, IIF(State = 's' AND Minperiod = 0, 'l', '') longtimesick
, NonSickDays
FROM periods