I have a problem with completing this pivot. I'm trying all sorts of stuff, but I just can't seem to get this correct. But as my luck usually runs, I might have to start over again, again, again.
I've looked here on stackoverflow, but nothing seems to fit my situation. As much as I can tell the other issues I've read through are for all numeric data. I have a mixture of numbers and string which might be the issue, but I just need a few more sets of eyes on this.
I'm writing a report which will display a row for each user in the system and their scores for each lesson they take. The pivoted columns represent the "lesson modules" and would display a score, "not started", or "incomplete".
The following is the the result of a few queries. This is correct:
"results"
+---------+-----------+--------------+-------------+
| user_id | module_id | total_failed | total_taken |
+---------+-----------+--------------+-------------+
| 605 | 89 | 0 | 0 |
| 605 | 90 | 0 | 0 |
| 605 | 91 | 0 | 0 |
| 606 | 89 | 2 | 3 |
| 606 | 90 | 1 | 4 |
| 606 | 91 | 0 | 0 |
| 634 | 89 | 0 | 3 |
| 634 | 90 | 0 | 4 |
| 634 | 91 | 0 | 0 |
+---------+-----------+--------------+-------------+
It is with this record set I need to pivot.
The user_id will remain in the first column, and the next three columns will pivot into the user's results for a number of column equal to the number of lessons. In this example, there will be three columns for lessons (modules) 89, 90. and 91.
I create a function "getModuleScore"
which returns one of three possible values: the user's score (0.0 =< x =< 1.0)
, or one of two literals: 'not started' or 'incomplete'. (This is the simplified explanation of what this function does - there's a little more to it than what I just wrote.)
If I use the following sql to pivot the previous results (the "results" table in the SQL)
SELECT
results.user_id AS user_id
,
MAX(CASE WHEN module_id = 89
THEN (SELECT getModuleScore(89, total_taken, total_failed))
ELSE
'not_started'
END)
AS `mod_89_score`
,
MAX(CASE WHEN module_id = 90
THEN (SELECT getModuleScore(90, total_taken, total_failed))
ELSE
'not_started'
END)
AS `mod_90_score`
,
MAX(CASE WHEN module_id = 91
THEN (SELECT getModuleScore(91, total_taken, total_failed))
ELSE
'not_started'
END)
AS `mod_91_score`
FROM
results
GROUP BY
results.user_id
, results.module_id
I receive the following record set.
+---------+--------------+--------------+--------------+
| user_id | mod_89_score | mod_90_score | mod_91_score |
+---------+--------------+--------------+--------------+
| 605 | not started | not_started | not_started |
| 605 | not_started | not started | not_started |
| 605 | not_started | not_started | not started |
| 606 | 0.333333333 | not_started | not_started |
| 606 | not_started | 0.750000000 | not_started |
| 606 | not_started | not_started | not started |
| 634 | 1.000000000 | not_started | not_started |
| 634 | not_started | 1.000000000 | not_started |
| 634 | not_started | not_started | not started |
+---------+--------------+--------------+--------------+
What I want is this:
+---------+--------------+--------------+--------------+
| user_id | mod_89_score | mod_90_score | mod_91_score |
+---------+--------------+--------------+--------------+
| 605 | not started | not_started | not_started |
| 606 | 0.333333333 | 0.750000000 | not_started |
| 634 | 1.000000000 | 1.000000000 | not_started |
+---------+--------------+--------------+--------------+
What I've tried:
@AgRizzo got it for me.
When I removed res.module_id
from the GROUP BY
clause, the result is what I'm looking for.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.