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 的多行中查找连续的日期

在 SQL Server 中拼接日期期间

sql server 生成连续日期

SQL Server连续日期 - 将多行汇总为连续的开始和结束日期行,而不包含CTE,循环,... s

使用间隙和孤岛查找连续的时间/日期 - SQL/BigQuery

Sql Server 查询一段日期内的全部礼拜天