简体   繁体   中英

MySQL Condition Excluding Some Desired Records

I have 5 tables which I want to join in MySQL to return a list of students who are enrolled in courses, the courses they are enrolled in, the assignments in those courses, and the grades the students earned on each assignment (or NULL, if the student has not completed the assignment).

table_students
id, name
1, John
2, Jacob
3, Jingleheimer
4, Schmidt

table_courses
id, name
20, English
30, Math 
40, Science

table_assignments
id, courseid, name
1, 20, English Assignment 1
2, 20, English Assignment 2
3, 20, English Assignment 3
4, 30, Math Assignment 1
5, 30, math Assignment 2
6, 40, Science Assignment 1
7, 40, Science Assignment 2
8, 40, Science Assignment 3
9, 40, Science Assignment 4

table_course_enrollments
studentid, courseid
1, 30
1, 40
3, 30
3, 20
4, 40

table_assignment_grades
studentid, courseid, assignmentid, grade
1, 30, 4, A
1, 40, 6, C
1, 40, 8, B
1, 40, 9, A
3, 30, 4, D

I want to return:

Student Name,Course Name, Assignment Name, Grade
John, Math, Math Assignment 1, A
John, Math, Math Assignment 2, Null
John, Science, Science Assignment 1, C
John, Science, Science Assignment 2, Null
John, Science, Science Assignment 3, B
John, Science, Science Assignment 4, D
Jingleheimer, Math, Math Assignment 1, D
Jingleheimer, Math, Math Assignment 2, Null
Jingleheimer, English, English Assignment 1, Null
Jingleheimer, English, English Assignment 2, Null
Schmidt, Science, Science Assignment 1, Null
Schmidt, Science, Science Assignment 2, Null
Schmidt, Science, Science Assignment 3, Null
Schmidt, Science, Science Assignment 4, Null

(No data for Jacob because he is not enrolled in any courses)

My Query:

SELECT table_students.name, table_courses.name, table_assignments.name, table_assignment_grades.grade

FROM table_students AS s
JOIN table_course_enrollments AS ce ON ce.userid=s.id
JOIN table_courses AS c ON c.id=ce.courseid
JOIN table_assignments AS a ON a.courseid=c.id
LEFT JOIN table_assignment_grades AS ag ON ag.userid=u.id

WHERE ag.assignmentid=a.id
AND ag.courseid=c.id

The result includes the students and courses as expected, but only grades and assignments the student has completed, instead of all assignments, completed or not. If I remove the WHERE clause, I get a list of all assignments, but the grades and the assignments are not matched to each other. The assignment_grades table needs to be joined to the student, the assignment AND the course in order to report correctly.

How can I rewrite this to return only students who are enrolled in courses, the assignments in those courses, and the grades for each assignment even if the assignment hasn't been graded?

Thanks so much for any tips! Kimber

Just putting the criteria from the WHERE in the last ON should fix it:

SELECT table_students.name, table_courses.name, table_assignments.name,
       table_assignment_grades.grade
FROM table_students AS s
JOIN table_course_enrollments AS ce ON ce.userid=s.id
JOIN table_courses AS c ON c.id=ce.courseid
JOIN table_assignments AS a ON a.courseid=c.id
LEFT JOIN table_assignment_grades AS ag ON ag.userid=u.id
   AND ag.assignmentid=a.id
   AND ag.courseid=c.id

You need to move your WHERE condition to your left join ON clause or you'll filter away all rows where there is no grade to show instead of setting them to NULL as you expect;

SELECT s.name sname, c.name cname, a.name aname, ag.grade
FROM table_students AS s
JOIN table_course_enrollments AS ce ON ce.studentid=s.id
JOIN table_courses AS c ON c.id=ce.courseid
JOIN table_assignments AS a ON a.courseid=c.id
LEFT JOIN table_assignment_grades AS ag 
  ON ag.studentid=s.id
 AND ag.assignmentid=a.id
 AND ag.courseid=c.id
ORDER BY s.id,c.id

An SQLfiddle to test with .

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM