将一对多关系视为列标题

时间:2012-12-05 18:12:39

标签: mysql sql pivot

我正在进行以下查询

    SELECT 
        p.id
        ,q.name
        ,pa.result
    FROM
        postulant_answers as pa
    LEFT OUTER JOIN postulants as p ON (p.id = pa.postulant_id)
    LEFT OUTER JOIN questions as q ON (q.id = pa.question_id);

向我展示了以下结果:

    +------+--------------+--------+
    | id   | name         | result |
    +------+--------------+--------+
    |    9 | Question 1   |     15 |
    |    9 | Question 2   |     70 |
    |    9 | Question 3   |     75 |
    |  591 | Question 1   |     15 |
    |  591 | Question 2   |     70 |
    |  591 | Question 3   |     75 |

但我需要更像的东西:

    +------+------------+------------+------------+
    | id   | Question 1 | Question 2 | Question 3 |
    +------+------------+------------+------------+
    |    9 |         15 |         70 |         75 |
    |  591 |         15 |         70 |         75 |

我可以只在一个查询中执行此操作吗? 任何帮助将不胜感激

1 个答案:

答案 0 :(得分:2)

这称为数据透视,但MySQL没有数据透视功能,因此您可以使用聚合函数和CASE实现此功能:

SELECT p.id,
  max(case when q.name = 'Question 1' then pa.result end) Question1,
  max(case when q.name = 'Question 2' then pa.result end) Question2,
  max(case when q.name = 'Question 3' then pa.result end) Question3
FROM postulant_answers as pa
LEFT OUTER JOIN postulants as p 
  ON (p.id = pa.postulant_id)
LEFT OUTER JOIN questions as q 
  ON (q.id = pa.question_id)
group by p.id

请参阅SQL Fiddle with Demo

结果:

|  ID | QUESTION1 | QUESTION2 | QUESTION3 |
-------------------------------------------
|   9 |        15 |        70 |        75 |
| 591 |        15 |        70 |        75 |

如果您有一定数量的问题,但如果问题的数量未知,那么您可以使用准备好的声明,类似于:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when q.name = ''',
      q.name,
      ''' then pa.result end) AS ',
      replace(name, ' ', '')
    )
  ) INTO @sql
FROM questions;

SET @sql = CONCAT('SELECT p.id, ', @sql, ' 
                  FROM postulant_answers as pa
                  LEFT OUTER JOIN postulants as p 
                    ON (p.id = pa.postulant_id)
                  LEFT OUTER JOIN questions as q 
                    ON (q.id = pa.question_id)
                  group by p.id');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

请参阅SQL Fiddle with Demo