Reputation: 121
I essentially have 2 models:
Students Classes
Each student can sign up for as many classes as they want. I wrote a simple query to count how many classes each student has signed up for, but cannot figure out how to include students who have chosen 0 classes. I am ultimately trying to see how many students have signed up for how many classes.
SELECT classes_chosen, count(*) AS student_count
FROM (SELECT students.email, count(*) AS classes_chosen
FROM students
JOIN students_classes ON students_classes.student_id = students.id
GROUP BY student_id) AS sub_q
GROUP BY classes_chosen
ORDER BY classes_chosen ASC;
I would like to end with something like:
classes_chosen, student_count
0, 47
1, 35
2, 45
3, 85
.
.
.
Upvotes: 0
Views: 83
Reputation: 164139
First aggregate inside students_classes
only to get how many classes has each student chosen and then LEFT
join students
to the results and aggregate again:
SELECT COALESCE(classes_chosen, 0) classes_chosen, COUNT(*) AS student_count
FROM students s
LEFT JOIN (
SELECT student_id, COUNT(*) AS classes_chosen
FROM students_classes
GROUP BY student_id
) AS c ON c.student_id = s.id
GROUP BY classes_chosen
ORDER BY classes_chosen ASC;
See a simplified demo.
Upvotes: 1
Reputation: 1270443
You can basically use LEFT JOIN
in the subquery:
SELECT classes_chosen, count(*) AS student_count
FROM (SELECT students.email, count(sc.student_id) AS classes_chosen
FROM students s LEFT JOIN
students_classes s
ON sc.student_id = s.id
GROUP BY student_id
) AS sub_q
GROUP BY classes_chosen
ORDER BY classes_chosen ASC;
Note: If all students have a matching class, then you will not get 0
in the result set. I interpret your question as wanting to count all students rather than particularly returning 0
.
Upvotes: 1