Reputation: 6132
I'm trying to LEFT JOIN on the same table multiple times, to get all the values of the specific topics. It works like I thought it would, see: http://sqlfiddle.com/#!9/9cda67/4
However, using the above fiddle, the database returns a single row for each different course. I'd like to group them, using GROUP BY PersonID
, but then it would only take the first value (a 6 for Math) and a (null)
value for all the other columns. See: http://sqlfiddle.com/#!9/9cda67/5
What do I need to change so that I get single row per Person, with all the grades filled in into their respective columns (when available)?
Upvotes: 0
Views: 1710
Reputation: 1269503
MySQL allows you to include columns in a SELECT
that are not in the GROUP BY
. This actually violates the ANSI standard and is not supported by any other database (although in some cases the ANSI standard does allow it). The result is indeterminate values from a single row in the output.
The solution is aggregation functions:
SELECT p.id AS PersonID, p.name AS PersonName,
max(pc1.grade) AS Math,
max(pc2.grade) AS Chemistry,
max(pc3.grade) AS Physics
FROM Person p LEFT JOIN
Person_Course pc
on p.id = pc.user_id LEFT JOIN
Course c on c.id = pc.course_id LEFT JOIN
Person_Course pc1
on pc1.id = pc.id AND pc1.course_id = 1 LEFT JOIN
Person_Course pc2
on pc2.id = pc.id AND pc2.course_id = 2 LEFT JOIN
Person_Course pc3
on pc3.id = pc.id AND pc3.course_id = 3
GROUP BY PersonID;
You might want group_concat()
if people could take the same course multiple times. Also, don't use single quotes for column names. Only use them for string and date constants.
Hardwiring the course ids into the code seems like a bad idea. I would write this more simply using conditional aggregation:
SELECT p.id AS PersonID, p.name AS PersonName,
max(case when c.name = 'Math' then pc.grade end) AS Math,
max(case when c.name = 'Chemistry' then pc.grade end) AS Chemistry,
max(case when c.name = 'Physics' then pc.grade end) AS Physics
FROM Person p LEFT JOIN
Person_Course pc
on p.id = pc.user_id LEFT JOIN
Course c
on c.id = pc.course_id
GROUP BY PersonID;
Upvotes: 2