I am just learning SQL and have run into a problem creating a custom report. I am working with school attendance data. I want to create a report that gives membership days and number of days for each absence type.
I have successfully created a report for these separately.
Membership Days (calculated by counting days school was in session between the student's entry date and the current date. Membership days does not exist as a field on its own)
SELECT sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp THEN cd.INSESSION ELSE 0 END), s.LASTFIRST
FROM CALENDAR_DAY cd,STUDENTS s
WHERE cd.SCHOOLID = 405
GROUP BY s.LASTFIRST
Count per absence type
SELECT s.STUDENT_NUMBER, s.LASTFIRST,SUM(CASE WHEN a.ATTENDANCE_CODEID = 2 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 4 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 3 THEN 1 ELSE 0 END),SUM(CASE WHEN a.ATTENDANCE_CODEID = 51 THEN 1 ELSE 0 END)
FROM ATTENDANCE a
INNER join STUDENTS s
ON a.STUDENTID = s.ID
WHERE a.att_date between '%param1%' and '%param2%'
GROUP BY s.STUDENT_NUMBER, s.LASTFIRST
The problem is that if I try to put these in the same report, the membership days are multiplied by the number of times the student appears in the attendance table due to joining student and attendance. My thought on a solution was to then divide this line
sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp THEN cd.INSESSION ELSE 0 END)
by the number of times the student showed up in the attendance table to counteract the student information existing on every line. I can't figure out how to do that. I don't know much about these types of problems, so hopefully I've just gone off on the wrong track and there is an easy solution. Thanks.
Your problem is a common problem -- trying to summarize along two dimensions at the same time without using a subquery. You want to do this query with two aggregation subqueries. Something like this:
SELECT *
FROM (SELECT sum(case when cd.DATE_VALUE >= s.ENTRYDATE and cd.DATE_VALUE <= current_timestamp
THEN cd.INSESSION
ELSE 0
END), s. STUDENT_NUMBER
FROM CALENDAR_DAY cd CROSS JOIN
STUDENTS s
WHERE cd.SCHOOLID = 405
GROUP BY s.STUDENT_NUMBER
) sc JOIN
(SELECT s.STUDENT_NUMBER, s.LASTFIRST,
SUM(CASE WHEN a.ATTENDANCE_CODEID = 2 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 4 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 3 THEN 1 ELSE 0 END),
SUM(CASE WHEN a.ATTENDANCE_CODEID = 51 THEN 1 ELSE 0 END)
FROM ATTENDANCE a INNER join
STUDENTS s
ON a.STUDENTID = s.ID
WHERE a.att_date between '%param1%' and '%param2%'
GROUP BY s.STUDENT_NUMBER, s.LASTFIRST
) sa
on sc.STUDENT_NUMBER = sa.STUDENT_NUMBER;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.