0

Is there a way in SQL of getting the data shown in the left table to be output as in the picture on the right?

enter image description here

RGriffiths
  • 5,722
  • 18
  • 72
  • 120
  • 1
    Possible duplicate of [MySQL pivot table](https://stackoverflow.com/questions/7674786/mysql-pivot-table) – Nick Feb 04 '19 at 11:40

1 Answers1

1

If you have a finite, static list of tests, and no user taking a test more then once, you can do it like this:

SELECT UserID, 
       SUM(Result * (Unit = "Test 1")) AS "Test 1",
       SUM(Result * (Unit = "Test 2")) AS "Test 2",
       SUM(Result * (Unit = "Test 3")) AS "Test 3" 
FROM table
GROUP BY UserID;

This works by using SUM over a GROUP as a weighted sum of all entries with a weight of 1 for the line with the matching test and 0 for all other lines (the comparison evaluates to 1 for TRUE and 0 for FALSE).

Edit

As @Nick pointed out in his comment, you can go a more readable and less implementation-dependent way using a CASE instead of the multiply-by-boolean style:

SELECT UserID, 
       SUM(CASE WHEN Unit = "Test 1" THEN Result ELSE 0 END) AS "Test 1",
       SUM(CASE WHEN Unit = "Test 2" THEN Result ELSE 0 END) AS "Test 2",
       SUM(CASE WHEN Unit = "Test 3" THEN Result ELSE 0 END) AS "Test 3"
FROM table
GROUP BY UserID;
Beppo
  • 176
  • 7
  • 2
    `SUM(CASE WHEN Unit = 'Test 1' THEN Result ELSE 0 END) AS \`Test 1\`` is more traditional and doesn't rely on a boolean being treated as 1 or 0. – Nick Feb 04 '19 at 11:40
  • I concurr, you are right, and it is probably better optimizable too. Didn't think that far :-) – Beppo Feb 04 '19 at 11:45
  • This work only if you have static units "test1","test2",... if you add new test cases you must update the query. It's bettere to use pivot tables, as described in https://stackoverflow.com/questions/7674786/mysql-pivot-table – Daniele Licitra Feb 04 '19 at 11:58