Matt Matt - 3 months ago 12
MySQL Question

MySQL pivot multi-row table to unique row table

I have the following table of results data in MySQL. I would like to pivot this around from a row per UPN per Subject Grade to a row per UPN so the table below:

UPN Collection Subject Grade
1 Target English 5
1 Current English 6
1 Target Maths 7
1 Current Maths 7
1 Target Art 6
1 Current Art 6
2 Target English 5
2 Current English 5
2 Target Maths 6
2 Current Maths 7
2 Target History 6
2 Current History 5


Should pivot around to the table below:

UPN English Current English Target Maths Current Maths Target Art Current Art Target History Current History Target
1 6 5 7 7 6 6 NULL NULL
2 5 5 7 6 NULL NULL 5 6


Please note that in the second table the UPN row must become unique, so no duplicate UPN rows containing NULLs.

Also where a UPN doesn't have a student then the cell value should be NULL.

SQL Fiddle

Answer

Try below query

SELECT t1.UPN,
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Current' AND t2.`Subject` = 'English'),NULL) AS 'English Current',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Target' AND t2.`Subject` = 'English'),NULL) AS 'English Target', 
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Current' AND t2.`Subject` = 'Maths'),NULL) AS 'Maths Current',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Target' AND t2.`Subject` = 'Maths'),NULL) AS 'Maths Target',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Current' AND t2.`Subject` = 'Art'),NULL) AS 'Art Current',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Target' AND t2.`Subject` = 'Art'),NULL) AS 'Art Target',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Current' AND t2.`Subject` = 'History'),NULL) AS 'History Current',
IFNULL((SELECT MAX(t2.Grade) FROM `results` AS t2 WHERE t2.UPN = t1.UPN AND t2.`Collection` = 'Target' AND t2.`Subject` = 'History'),NULL) AS 'History Target'
FROM `results` AS t1 GROUP BY t1.`UPN`