按行分组并从同一个表中选择多个规范化列

时间:2017-02-02 10:02:26

标签: mysql

我尝试过快速搜索,但找不到任何可以帮助的内容(或者不知道正确的术语)

这是我桌子的ERD:

ERD of my tables

以下是相关表格的一些示例数据:

+------------+----------------+-------+
| sport_id   | sport_name     | type  |
+------------+----------------+-------+
| 1          | 100M           | track |
| 2          | 200M           | track |
| 3          | Javelin        | field |
+---+------------+------------+-------+
+------------+----------------+-------------+
| pupil_id   | pupil_name     | pupil_class |
+------------+----------------+-------------+
| 1          | John Doe       | 1A          |
| 2          | Lisa Lawson    | 1K          |
| 3          | Jamie Wilson   | 1F          |
+---+------------+------------+-------------+
+----------+----------+----------+-------+
| pupil_id | sport_id | attempt  | score |
+----------+----------+----------+-------+
| 1        | 3        | 1        | 20    |
| 1        | 3        | 2        | 30    |
| 1        | 3        | 3        | 40    |
| 2        | 3        | 1        | 22    |
| 2        | 3        | 2        | 32    |
| 2        | 3        | 3        | 33    |
| 3        | 3        | 1        | 23    |
| 3        | 3        | 2        | 33    |
| 3        | 3        | 3        | 43    |
+----------+----------+----------+-------+

对于选定的pupil_name,我想要做的最终是sport_id及其所有尝试,例如WHERE sport.sport_id = 3

+--------------+--------+--------+--------+
| pupil_name   | score1 | score2 | score3 |
+--------------+--------+--------+--------+
| John Doe     | 20     | 30     | 40     |
| Lisa Lawson  | 22     | 32     | 42     |
| Jamie Wilson | 23     | 33     | 43     |
+---+------------+------------+-----------+

我有以下查询,它只是连接表,我尝试使用子查询来获取分数,但我无法将pupil_id传递给子查询(因此返回NULL)。这也会返回pupil_name三次:

SELECT p.pupil_name, 
       (SELECT score 
        FROM   result 
        WHERE  attempt = 1 
               AND pupil_id = p.pupil_id) AS score1 
FROM   pupil p, 
       sport s, 
       result r 
WHERE  p.pupil_id = r.pupil_id 
       AND s.sport_id = r.sport_id 
       AND r.sport_id = 3; 

示例结果:

+--------------+--------+
| pupil_name   | score1 |
+--------------+--------+
| John Doe     | NULL   |
| John Doe     | NULL   |
| John Doe     | NULL   | 
+---+------------+------+

我该如何处理?我可以使用JOIN吗?

1 个答案:

答案 0 :(得分:1)

解决方案1:3 INNER JOIN

这是一个使用3个简单INNER JOIN的解决方案:

SELECT p.pupil_name
        ,r1.score AS score1
        ,r2.score AS score2
        ,r3.score AS score3
FROM pupil p
    INNER JOIN result r1
        ON p.pupil_id = r1.pupil_id
        AND r1.attempt = 1
    INNER JOIN result r2
        ON p.pupil_id = r2.pupil_id
        AND r2.attempt = 1
    INNER JOIN result r3
        ON p.pupil_id = r3.pupil_id
        AND r3.attempt = 1
    INNER JOIN sport s
        ON r1.sport_id = s.sport_id
        AND r2.sport_id = s.sport_id
        AND r3.sport_id = s.sport_id
WHERE s.sport_id = 3
;

解决方案2:1 INNER JOIN和GROUP BY

此解决方案仅对INNER JOIN表使用1 result,然后以巧妙的方式聚合值:

SELECT   p.pupil_name
        ,MAX(CASE WHEN r.attempt = 1 THEN r.score END) AS score1
        ,MAX(CASE WHEN r.attempt = 2 THEN r.score END) AS score2
        ,MAX(CASE WHEN r.attempt = 3 THEN r.score END) AS score3
FROM pupil p
    INNER JOIN result r
        ON p.pupil_id = r.pupil_id
    INNER JOIN sport s
        ON r.sport_id = s.sport_id
WHERE s.sport_id = 3
GROUP BY p.pupil_name
;