TSQL计算连续缺勤的次数
问题:* 我正在尝试计算每个学生在特定课程中连续缺勤的次数。但是,如果该学生确实上课了一天,则需要重新开始计数。
例如,如果班级MATH1234在周一和周五上课,学生001234错过了第一周的周一、周五和第二周的周一,但参加了第二周的周五,然后错过了周一和周五第三周的星期五,他们该课程的连续缺席计数为:(
这是我的课程表的缩减版本)
上课日周缺席连续 Abs MATH1234 星期一 1 1 1 MATH1234 星期五 1 1 2 MATH1234 周一 2 1 3 MATH1234 星期五 2 0 0 MATH1234 周一 3 1 1 MATH1234 周五 3 1 2
我有一个名为课程的表,其中包含所有学生及其注册的课程以及他们是否缺席任何课程的运行列表:
课程([学生 ID ]、[班级编号]、[行号]、[学期间]、[年份]、[学期]、[周]、[日期间]、[班级日期]、[缺席]、[原因代码]、[连续Abs])
鉴于上表,我目前正在做的是更新 Lessons 表,更改 ConsecutiveAbs 的值,如下所示:
UPDATE Lessons
SET ConsecutiveAbs =
(SELECT ISNULL(SUM(CAST(IsAbsent AS numeric)), 0)
FROM Lessons AS L3
WHERE L3.IsAbsent = 1
AND L1.IsAbsent <> 0
AND L3.[Student ID] = L1.[Student ID]
AND L3.[Class Number] = L1.[Class Number]
AND L3.[Line Number] = L1.[Line Number]
AND L3.[Year] = L1.[Year]
AND L3.[ClassDate] <= L1.[ClassDate]
AND (L3.[ClassDate] > (SELECT MAX(L2.ClassDate)
FROM Lessons AS L2
WHERE L2.IsAbsent = 0
AND L2.[Student ID] = L1.[Student ID]
AND L2.[Class Number] = L1.[Class Number]
AND L2.[Line Number] = L1.[Line Number]
AND L2.[Year] = L1.[Year]
AND L2.ClassDate < L1.[ClassDate]
) OR (SELECT MAX(L2.ClassDate)
FROM Lessons AS L2
WHERE L2.IsAbsent = 0
AND L2.[Student ID] = L1.[Student ID]
AND L2.[Class Number] = L1.[Class Number]
AND L2.[Line Number] = L1.[Line Number]
AND L2.[Year] = L1.[Year]
AND L2.ClassDate < L1.[ClassDate]
) IS NULL))
FROM Lessons AS L1
但这忽略了学生实际参加的课程,只是继续计数:(
上课日周缺席连续 Abs MATH1234 星期一 1 1 1 MATH1234 星期五 1 1 2 MATH1234 周一 2 1 3 MATH1234 星期五 2 0 4 MATH1234 周一 3 1 5 MATH1234 周五 3 1 6
有什么想法吗?
Problem:* I'm trying to calculate the number of consecutive absence each student have for a particular class. However, the count need to be restarted if that student did attend class for one day.
e.g. If class MATH1234 has classes on Monday and Friday and student 001234 missed Monday, Friday for Week 1 and Monday for Week 2 but attended Friday for Week 2, then missed Monday and Friday for Week 3, their consecutive absence count for that class would be:
(this is a cut down version of my Lessons table)
Class Day Week IsAbsent ConsecutiveAbs MATH1234 Mon 1 1 1 MATH1234 Fri 1 1 2 MATH1234 Mon 2 1 3 MATH1234 Fri 2 0 0 MATH1234 Mon 3 1 1 MATH1234 Fri 3 1 2
I have a table called Lessons that contain a running list of all the students and the classes they are enrolled in and whether they were absent for any classes:
Lessons([Student ID], [Class Number], [Line Number], [Academic Period], [Year], [Term], [Week], [Day Period], [ClassDate], [IsAbsent], [ReasonCode], [ConsecutiveAbs])
Given the table above, what I am currently doing is Updating the Lessons table change the value of ConsecutiveAbs like this:
UPDATE Lessons
SET ConsecutiveAbs =
(SELECT ISNULL(SUM(CAST(IsAbsent AS numeric)), 0)
FROM Lessons AS L3
WHERE L3.IsAbsent = 1
AND L1.IsAbsent <> 0
AND L3.[Student ID] = L1.[Student ID]
AND L3.[Class Number] = L1.[Class Number]
AND L3.[Line Number] = L1.[Line Number]
AND L3.[Year] = L1.[Year]
AND L3.[ClassDate] <= L1.[ClassDate]
AND (L3.[ClassDate] > (SELECT MAX(L2.ClassDate)
FROM Lessons AS L2
WHERE L2.IsAbsent = 0
AND L2.[Student ID] = L1.[Student ID]
AND L2.[Class Number] = L1.[Class Number]
AND L2.[Line Number] = L1.[Line Number]
AND L2.[Year] = L1.[Year]
AND L2.ClassDate < L1.[ClassDate]
) OR (SELECT MAX(L2.ClassDate)
FROM Lessons AS L2
WHERE L2.IsAbsent = 0
AND L2.[Student ID] = L1.[Student ID]
AND L2.[Class Number] = L1.[Class Number]
AND L2.[Line Number] = L1.[Line Number]
AND L2.[Year] = L1.[Year]
AND L2.ClassDate < L1.[ClassDate]
) IS NULL))
FROM Lessons AS L1
But that disregard the classes where the student actually attended the class and just kept counting :(
Class Day Week IsAbsent ConsecutiveAbs MATH1234 Mon 1 1 1 MATH1234 Fri 1 1 2 MATH1234 Mon 2 1 3 MATH1234 Fri 2 0 4 MATH1234 Mon 3 1 5 MATH1234 Fri 3 1 6
Any idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
与您上一个问题的答案类似,只是这一次它会查找已参加过的课程,而不仅仅是将搜索限制为一周。
Similar to the answer to your previous question, only this time it looks for a class that has been attended, instead of just limiting the search by a week.
根据您的情况,这可能没有用,但它可能会帮助您找到解决方案
This may not be useful depending on your scenario but it may help you get to the solution
像这样的东西吗?
编辑:
添加您的更新。
编辑2:添加了更新
Something like this?
Edit:
Add your update around.
Edit2: Added the update
不确定您是否想坚持子查询的想法。这种问题类型 -IMO - 使用游标可以更好地解决(更快,更简单)。如果您选择走这条路线,那么 SQL 将如下所示。
所以不允许我将代码粘贴到答案中。所以我把代码片段粘贴在这里。 http://pastebin.com/ybesdX2G
这是向您展示如何使用光标的文章的参考。 http://msdn.microsoft.com/en-us/library/ms180169.aspx编辑
:
游标方法一次只处理一行,并记住最后一行是否缺失/存在。因此正确排序数据很重要。
请注意,代码片段中没有 ORDER BY。我根据您在问题中提供的数据示例测试了代码片段。您的数据已预先排序。所以,它就像一个魅力。
在你的数据库中,如果你的数据没有以预先排序的方式存储(我怀疑是这样),你将需要在第 8 行添加一个 ORDER BY,以将数据排序到序列中。
希望这有帮助。
Not sure if you are looking to stick to the subquery idea. This problem type -IMO -is better solved (quicker, less complex) using cursors. Here is what the SQL would look like if you choose to go that route.
So didn't let me to paste the code in the answer. So I've pasted the code snippet here. http://pastebin.com/ybesdX2G
Here's a reference to the article showing you how to do cursors. http://msdn.microsoft.com/en-us/library/ms180169.aspx
Edit:
The cursor approach works on one row at a time and remembers whether the last row was absent/present. So sorting the data correctly is important.
Notice that there is no ORDER BY in the code snippet. I tested the code snippet against data sample you had provided in the question. Your data was pre-sorted. So, it worked like a charm.
In your database if your data isn't stored in a pre-sorted fashion(which I doubt it is) you will want to add an ORDER BY to line #8, to sort the data into the sequence.
Hope this helps.