简体   繁体   中英

MySql pivot not condensing grouped rows

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:

  1. I've already reworte the inner queries to give me the correct data to calculate with
  2. Enclosed the CASE clauses in MAX(), MIN(), and SUM()
  3. Removed the ELSE on the CASE clauses which gives me NULLS in the result set
  4. Changed the GROUP BY clause

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM