I am using MySQL.
I have a table grades
, that looks like so:
course_id grade 101 90 101 100 101 100 102 92 102 85 102 90
I have a view that counts how many grades are in each bin, for each class using the following query.
SELECT *, COUNT(grade_bin) as count FROM (SELECT course_id, FLOOR(grade/5.00)*5 AS grade_bin FROM ranked_grades) as t GROUP BY course_id, grade_bin ORDER BY course_id, grade_bin ASC;
This returns:
course_id grade_bin count 101 90 1 101 100 2 102 85 1 102 90 2
I want to add empty bins to this view, like so:
course_id grade_bin count 101 40 0 101 45 0 ... ... ... 101 100 2 102 40 0 ... ... ...
So the bins increment by 5, starting at 40, and stopping at 100. My thought was to make a table for empty bins, insert each grade bin and a count of 0, then use UNION
but I can’t get the UNION
to work, since I don’t have the course_id
column in the empty bin table (nor do I want to – there are a lot and they could change). How would I do a UNION for each group of course_ids
?
Advertisement
Answer
Assuming that you have created the table bin_table
with only 1 column grade_bin
and values 40, 45, 50, …., 100 and also that you have a table cources
with the column course_id
as primary key, all you have to do is CROSS
join these tables and LEFT
join to a query that aggregates on the table ranked_grades
(no subquery needed):
SELECT c.course_id, b.grade_bin, COALESCE(t.count, 0) AS count FROM bin_table b CROSS JOIN cources c LEFT JOIN ( SELECT course_id, FLOOR(grade / 5.00) * 5 AS grade_bin, COUNT(*) AS count FROM ranked_grades GROUP BY course_id, grade_bin ) t ON (t.course_id, t.grade_bin) = (c.course_id, b.grade_bin)