SQL Server:查找学生在自定义日期内的连续缺勤计数
Posted
技术标签:
【中文标题】SQL Server:查找学生在自定义日期内的连续缺勤计数【英文标题】:SQL Server : finding consecutive absence counts for students over custom dates 【发布时间】:2017-02-25 13:59:04 【问题描述】:我有一张表格,用于存储学生每天的出勤情况。我需要让连续缺勤3天的学生。但是,考勤的日期没有顺序,不包括缺勤、节假日、周末等一些日子。学生参加的日期是该表中存在记录的日期。
数据是这样的
StudentId Date Attendance
-----------------------------------------
178234 1/1/2017 P
178234 5/1/2107 A
178234 6/1/2107 A
178234 11/1/2107 A
178432 1/1/2107 P
178432 5/1/2107 A
178432 6/1/2107 P
178432 11/1/2107 A
在上述情况下,结果应该是
StudentId AbsenceStartDate AbsenceEndDate ConsecutiveAbsences
----------------------------------------------------------------------------
178234 5/1/2017 11/1/2017 3
我已尝试实施此解决方案Calculating Consecutive Absences in SQL 但仅适用于按顺序排列的日期。任何建议都会很棒,谢谢
【问题讨论】:
xkcd PSA ISO 8601 学生就读的日期是该表中存在记录的日期 所以要确认一下,学生应该参加的所有日期都记录在表中,Attendance
列告诉您他们是否在场 (P) 或缺席 (A)那天?
这可能有助于***.com/questions/14953294/…
【参考方案1】:
哦,你的桌子上有缺席和礼物。你可以使用row_numbers()
的区别方法:
select studentid, min(date), max(date)
from (select a.*,
row_number() over (partition by studentid order by date) as seqnum,
row_number() over (partition by studentid, attendance order by date) as seqnum_a
from attendance a
) a
where attendance = 'A'
group by studentid, (seqnum - seqnum_a)
having count(*) >= 3;
行号的不同得到相同的连续值。这有点难以理解,但是如果您运行子查询,您应该会看到连续缺席或出席的差异是如何保持不变的。您只关心缺勤,因此外部查询中的 where
。
【讨论】:
很好的答案,我花了一些时间才真正理解。【参考方案2】:试试这个:
declare @t table (sid int, d date, att char(1))
insert @t (sid,d, att) values
(178234, '1/1/2017','P'),
(178234, '5/1/2017','A'),
(178234, '6/1/2017','A'),
(178234, '11/1/2017','A'),
(178432, '1/1/2017','P'),
(178432, '5/1/2017','A'),
(178432, '6/1/2017','P'),
(178432, '11/1/2017','A')
Select s.sid, Min(s.d) startDt, Max(e.d) endDt, s.att, e.att, count(*)
from @t s join @t e on e.d <=
(select max(d) from @t m
Where sid = s.sid
and d > s.d
and att = 'A'
and not exists
(Select * from @t
where sid = s.sid
and d between s.d and m.d
and att = 'P'))
Where s.att = 'A'
and s.d = (Select Min(d) from @t
Where sid = s.sid
and d < e.d
and att = 'A')
group by s.sid, s.d, s.att, e.att
这也很难解释: 基本上,它使用别名 s(代表开始)和 e(代表结束)将表连接到自身,其中 s-row 是一组连续缺席的第一行,而 e.行都是在螺柱出现的下一个日期之前的缺勤之后。这将生成一组没有 P 行的所有“A”。然后 sql 按适当的值分组以返回每个组中的最早和最晚日期以及行数。 最后一个 where 子句确保 s 行是组中的第一行。
【讨论】:
以上是关于SQL Server:查找学生在自定义日期内的连续缺勤计数的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s