SQL Server:查找自定义日期内学生的连续缺勤计数
我有一张桌子,上面放着学生每天的出席人数。我需要找连续缺席3天的学生。然而,出勤日期不按顺序排列,有些日子如不出勤、节假日、周末不包括在内。学生上课的日期是该表中记录的日期 数据如下SQL Server:查找自定义日期内学生的连续缺勤计数,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一张桌子,上面放着学生每天的出席人数。我需要找连续缺席3天的学生。然而,出勤日期不按顺序排列,有些日子如不出勤、节假日、周末不包括在内。学生上课的日期是该表中记录的日期 数据如下 StudentId Date Attendance ----------------------------------------- 178234 1/1/2017 P 178234 5/1/2107 A 17
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
我已经尝试过实现这个解决方案,但是它只对日期起作用。任何建议都很好,谢谢。哦,你的桌子上有缺席和礼物。您可以使用
行数()的差异方法:
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
。尝试以下操作:
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
declare@t表(sid int,d日期,att char(1))
插入@t(sid、d、att)值
(178234,'2017年1月1日','P'),
(178234,'2017年5月1日','A'),
(178234,'6/1/2017','A'),
(178234,'2017年11月1日','A'),
(178432,“2017年1月1日”,“P”),
(178432,'5/1/2017','A'),
(178432,'6/1/2017','P'),
(178432,‘2017年11月1日’,‘A’)
选择s.sid、最小(s.d)开始时间、最大(e.d)结束时间、s.att、e.att、计数(*)
从@t s在e.d s.d上加入@t e
和att='A'
而且不存在
(从@t中选择*
其中sid=s.sid
d在s.d和m.d之间
和att='P'))
其中s.att='A'
和s.d=(从@t中选择Min(d)
其中sid=s.sid
d
这也很难解释:
基本上,它使用别名s(表示开始)和e(表示结束)将表连接到自身,其中s行是一组连续缺勤中的第一行,而e行是。行是指在螺柱出现的下一个日期之前的所有缺勤。这将生成一组内没有P行的所有“a”。然后,sql按适当的值分组,以返回每个组中最早和最晚的日期以及行数。
最后一个where子句确保s行是组中的第一行。学生出席的日期是该表中存在记录的日期。要确认,学生本应出席的所有日期都记录在该表中,出席
列告诉您他们是否出席(p)(A) 在那一天?这可能会帮助我得到一个很好的答案,我花了一些时间才真正理解。