我的Microsoft SQL Server 2016中有以下Attendance
表:
ID StudentID Date AbsenceReasonID
----------------------------------------------------
430957 10158 2018-02-02 2
430958 10158 2018-02-03 2
430959 10158 2018-02-04 11
430960 12393 2018-03-15 9
430961 1 2018-03-15 9
430962 12400 2018-03-15 9
430963 5959 2018-03-15 11
我希望有一个查询可以检索一组行,其中Date
列连续发生了3个或更多个缺席,仅供单个学生(StudentID
)使用。理想情况下,运行查询后的以下数据将是
ID StudentID Date AbsenceReasonID
----------------------------------------------------
430957 10158 2018-02-02 2
430958 10158 2018-02-03 2
430959 10158 2018-02-04 11
请注意,如果学生在星期五缺席,我希望在周末到周一(无视周末日期)进行。
如果需要更多信息以更好地帮助您协助我,请告诉我。我使用了以下查询作为启动器,但知道它不是我要找的:
SELECT
CONVERT(datetime, A.DateOF, 103),
A.SchoolNum, EI.FullName,
COUNT(A.SchoolNum) as 'Absences'
FROM
Attendance A
INNER JOIN
EntityInformation EI ON EI.SchoolNum = A.SchoolNum AND EI.Deleted = 0
INNER JOIN
Enrolment E ON EI.SchoolNum = E.SchoolNum AND E.Deleted = 0
GROUP BY
A.SchoolNum, A.DateOf, FullName
HAVING
COUNT(A.SchoolNum) > 1
AND A.DateOf = GETDATE()
AND A.SchoolNum in (SELECT SchoolNum FROM Attendance A1
WHERE A1.DateOf = A.DateOf -7)
这是一个静态解决方案,用于检索学生的ID在过去7天内发生过两次的缺席。这既不是连续的,也不是三天或更多天。
答案 0 :(得分:0)
如果你需要在一段时间内得到缺席(让我们说过去7天),那么你可以做这样的事情
SELECT
ID,
StudentID,
[Date],
AbsenceReasonID
FROM(
SELECT
ID,
StudentID,
[Date],
AbsenceReasonID,
COUNT(StudentID) OVER(PARTITION BY StudentID ORDER BY StudentID) AS con,
((DATEPART(dw, [Date]) + @@DATEFIRST) % 7) AS dw
FROM attendance
) D
WHERE
D.con > 2
AND [Date] >= '2018-02-02'
AND [Date] <= GETDATE()
AND dw NOT IN(0,1)
并根据您的给定数据输出
| ID | StudentID | Date | AbsenceReasonID |
|--------|-----------|------------|-----------------|
| 430957 | 10158 | 2018-02-02 | 2 |
您可以根据需要调整输出。
答案 1 :(得分:0)
试试这个:
CTE
包含学生在前一天和后一天(周末除外)缺席的缺席日期。最后的2 UNION
会添加每组的第一个和最后一个,并消除重复项。
with cte(id, studentId, dateof , absenceReasonId)
as
(
select a.*
from attendance a
where exists (select 1 from attendance preva
where preva.studentID = a.studentID
and datediff(day, preva.dateof, a.dateof)
<= (case when datepart(dw, preva.dateof) >= 5
then 8 - datepart(dw, preva.dateof)
else 1
end)
and preva.dateof < a.dateof)
and exists (select 1 from attendance nexta
where nexta.studentID = a.studentID
and datediff(day, a.dateof, nexta.dateof)
<= (case when datepart(dw, a.dateof) >= 5
then 8 - datepart(dw, a.dateof)
else 1
end)
and nexta.dateof > a.dateof))
select cte.*
from cte
union -- use union to remove duplicates
select preva.*
from
attendance preva
inner join
cte
on preva.studentID = cte.studentID
and preva.dateof < cte.dateof
and datediff(day, preva.dateof, cte.dateof)
<= (case when datepart(dw, preva.dateof) >= 5
then 8 - datepart(dw, preva.dateof)
else 1
end)
union
select nexta.*
from attendance nexta
inner join
cte
on nexta.studentID = cte.studentID
and datediff(day, cte.dateof, nexta.dateof)
<= (case when datepart(dw, cte.dateof) >= 5
then 8 - datepart(dw, cte.dateof)
else 1
end)
and nexta.dateof > cte.dateof
order by studentId, dateof
答案 2 :(得分:0)
您可以使用它来查找缺席范围。在这里,我使用递归CTE
对几年内的所有日期进行编号,同时记录他们的工作日。然后使用另一个递归CASE WHEN
来加入同一个学生的缺席日期,考虑周末应该被跳过(阅读连接条款的SET DATEFIRST 1 -- Monday = 1, Sunday = 7
;WITH Days AS
(
-- Recursive anchor: hard-coded first date
SELECT
GeneratedDate = CONVERT(DATE, '2017-01-01')
UNION ALL
-- Recursive expression: all days until day X
SELECT
GeneratedDate = DATEADD(DAY, 1, D.GeneratedDate)
FROM
Days AS D
WHERE
DATEADD(DAY, 1, D.GeneratedDate) <= '2020-01-01'
),
NumberedDays AS
(
SELECT
GeneratedDate = D.GeneratedDate,
DayOfWeek = DATEPART(WEEKDAY, D.GeneratedDate),
DayNumber = ROW_NUMBER() OVER (ORDER BY D.GeneratedDate ASC)
FROM
Days AS D
),
AttendancesWithNumberedDays AS
(
SELECT
A.*,
N.*
FROM
Attendance AS A
INNER JOIN NumberedDays AS N ON A.Date = N.GeneratedDate
),
AbsenceSpree AS
(
-- Recursive anchor: absence day with no previous absence, skipping weekends
SELECT
StartingAbsenceDate = A.Date,
CurrentDateNumber = A.DayNumber,
CurrentDateDayOfWeek = A.DayOfWeek,
AbsenceDays = 1,
StudentID = A.StudentID
FROM
AttendancesWithNumberedDays AS A
WHERE
NOT EXISTS (
SELECT
'no previous absence date'
FROM
AttendancesWithNumberedDays AS X
WHERE
X.StudentID = A.StudentID AND
X.DayNumber = CASE A.DayOfWeek
WHEN 1 THEN A.DayNumber - 3 -- When monday then friday (-3)
WHEN 7 THEN A.DayNumber - 2 -- When sunday then friday (-2)
ELSE A.DayNumber - 1 END)
UNION ALL
-- Recursive expression: find the next absence day, skipping weekends
SELECT
StartingAbsenceDate = S.StartingAbsenceDate,
CurrentDateNumber = A.DayNumber,
CurrentDateDayOfWeek = A.DayOfWeek,
AbsenceDays = S.AbsenceDays + 1,
StudentID = A.StudentID
FROM
AbsenceSpree AS S
INNER JOIN AttendancesWithNumberedDays AS A ON
S.StudentID = A.StudentID AND
A.DayNumber = CASE S.CurrentDateDayOfWeek
WHEN 5 THEN S.CurrentDateNumber + 3 -- When friday then monday (+3)
WHEN 6 THEN S.CurrentDateNumber + 2 -- When saturday then monday (+2)
ELSE S.CurrentDateNumber + 1 END
)
SELECT
StudentID = A.StudentID,
StartingAbsenceDate = A.StartingAbsenceDate,
EndingAbsenceDate = MAX(N.GeneratedDate),
AbsenceDays = MAX(A.AbsenceDays)
FROM
AbsenceSpree AS A
INNER JOIN NumberedDays AS N ON A.CurrentDateNumber = N.DayNumber
GROUP BY
A.StudentID,
A.StartingAbsenceDate
HAVING
MAX(A.AbsenceDays) >= 3
OPTION
(MAXRECURSION 5000)
)。最后显示每个缺席狂欢连续N天过滤。
SELECT
StudentID = A.StudentID,
StartingAbsenceDate = A.StartingAbsenceDate,
EndingAbsenceDate = MAX(N.GeneratedDate),
AbsenceDays = MAX(A.AbsenceDays)
FROM
AbsenceSpree AS A
INNER JOIN NumberedDays AS N ON A.CurrentDateNumber = N.DayNumber
GROUP BY
A.StudentID,
A.StartingAbsenceDate
HAVING
MAX(A.AbsenceDays) >= 3
如果要列出原始出勤表行,可以替换最后一个选择:
CTE + SELECT
使用此,
FilteredAbsenceSpree AS
(
SELECT
StudentID = A.StudentID,
StartingAbsenceDate = A.StartingAbsenceDate,
EndingAbsenceDate = MAX(N.GeneratedDate),
AbsenceDays = MAX(A.AbsenceDays)
FROM
AbsenceSpree AS A
INNER JOIN NumberedDays AS N ON A.CurrentDateNumber = N.DayNumber
GROUP BY
A.StudentID,
A.StartingAbsenceDate
HAVING
MAX(A.AbsenceDays) >= 3
)
SELECT
A.*
FROM
Attendance AS A
INNER JOIN FilteredAbsenceSpree AS F ON A.StudentID = F.StudentID
WHERE
A.Date BETWEEN F.StartingAbsenceDate AND F.EndingAbsenceDate
OPTION
(MAXRECURSION 5000)
:
$(document).ready(function(){
$.ajax({
type: "POST",
url: "https://api.rss2json.com/v1/api.json?rss_url=https://yourblog/feed/",
success: function(data, textStatus) {
var j=1;
for(var i=0;i<data.items.length;i++){
your functionalities;
} } });
});