根据每日粒度的事实数据表计算日期间隔



我有经过一些转换后获得的学生缺勤数据。数据是逐天的:

WITH datasample AS (
SELECT 1 AS StudentID, 20180101 AS DateID, 0 AS AbsentToday, 0 AS AbsentYesterday UNION ALL
SELECT 1, 20180102, 1, 0 UNION ALL
SELECT 1, 20180103, 1, 1 UNION ALL
SELECT 1, 20180104, 1, 1 UNION ALL
SELECT 1, 20180105, 1, 1 UNION ALL
SELECT 1, 20180106, 0, 1 UNION ALL
SELECT 2, 20180101, 0, 0 UNION ALL
SELECT 2, 20180102, 1, 0 UNION ALL
SELECT 2, 20180103, 1, 1 UNION ALL
SELECT 2, 20180104, 0, 1 UNION ALL
SELECT 2, 20180105, 1, 0 UNION ALL
SELECT 2, 20180106, 1, 1 UNION ALL
SELECT 2, 20180107, 0, 1
)
SELECT *
FROM datasample
ORDER BY StudentID, DateID

我需要添加一列(缺席期在月(,用于计算学生在当月的缺勤期。 例如,StudentID=1 在当月连续一个时间段内不存在,而 StudentID=2 有两个时间段,如下所示:

StudentID DateID    AbsentToday AbsentYesterday AbsencePeriodInMonth
1         20180101  0           0               0
1         20180102  1           0               1
1         20180103  1           1               1
1         20180104  1           1               1
1         20180105  1           1               1
1         20180106  0           1               0
2         20180101  0           0               0
2         20180102  1           0               1
2         20180103  1           1               1
2         20180104  0           1               0
2         20180105  1           0               2
2         20180106  1           1               2
2         20180107  0           1               0

我的目标实际上是计算事实表中每天之前的连续缺勤天数,我想如果我得到 AbsencePeriodInMonth 列,我可以做到这一点,方法是将其添加到 * 之后的查询中:

,CASE WHEN AbsentToday = 1 THEN DENSE_RANK() OVER(PARTITION BY StudentID, AbsencePeriodInMonth ORDER BY DateID)
ELSE 0
END AS DaysAbsent

关于我如何添加缺勤期InMonth或以其他方式计算连续缺勤天数的任何想法?

您可以通过事先计算 0 的数量来识别每个周期。 然后,您可以使用dense_rank()枚举它们。

select ds.*,
(case when absenttoday = 1 then dense_rank() over (partition by studentid order by grp)
else 0
end) as AbsencePeriodInMonth
from (select ds.*, sum(case when absenttoday = 0 then 1 else 0 end) over (partition by studentid order by dateid) as grp
from datasample ds
) ds
order by StudentID, DateID;

这是一个SQL小提琴。

使用Recursive CTEDense_Rank

WITH datasample AS (
SELECT 1 AS StudentID, 20180101 AS DateID, 0 AS AbsentToday, 0 AS AbsentYesterday UNION ALL
SELECT 1, 20180102, 1, 0 UNION ALL
SELECT 1, 20180103, 1, 1 UNION ALL
SELECT 1, 20180104, 1, 1 UNION ALL
SELECT 1, 20180105, 1, 1 UNION ALL
SELECT 1, 20180106, 0, 1 UNION ALL
SELECT 2, 20180101, 0, 0 UNION ALL
SELECT 2, 20180102, 1, 0 UNION ALL
SELECT 2, 20180103, 1, 1 UNION ALL
SELECT 2, 20180104, 0, 1 UNION ALL
SELECT 2, 20180105, 1, 0 UNION ALL
SELECT 2, 20180106, 1, 1 UNION ALL
SELECT 2, 20180107, 0, 1
), cte as
(Select *,DateID as dd 
from datasample 
where AbsentToday = 1 and AbsentYesterday = 0
union all
Select d.*, c.dd 
from datasample d
join cte c
on d.StudentID = c.StudentID and d.DateID = c.DateID + 1 
where d.AbsentToday = 1
), cte1 as
(
Select *, DENSE_RANK() over (partition by StudentId order by dd) as de 
from cte
)
Select d.*, IsNull(c.de,0) as AbsencePeriodInMonth
from cte1 c 
right join datasample d
on d.StudentID = c.StudentID and c.DateID = d.DateID
order  by d.StudentID, d.DateID

最新更新