在MySQL中,如何获取每天的每个条目的值?

时间:2013-03-22 13:10:18

标签: mysql sql pivot

所以,我有一个类似于这个的MySQL表:

|Day | Participant| Score |
+----+------------+-------+
|Mon | Andy       | 9     |
|Mon | Betty      | 8     |
|Mon | Charlie    | 7     |
|Tue | Andy       | 6     |
|Tue | Betty      | 6     |
|Tue | Charlie    | 8     |
|Wed | Andy       | 7     |
|Wed | Charlie    | 4     |

我想将其输出到:

| Day | Andy | Betty | Charlie |
+-----+------+-------+---------+
| Mon | 9    | 8     | 7       |
| Tue | 6    | 6     | 7       |
| Wed | 7    | null  | 4       |

我用PHP解决了这个问题,这就是我想出来的:

  1. 查询每个参与者的姓名。
  2. 使用PHP,每天为每个参与者的分数构建一个子查询,如下所示:

    SELECT score FROM TableName WHERE (Day=ref_point AND Participant='Andy')
    
  3. 生成包含所有子查询的主查询,如下所示:

    SELECT Day AS ref_point,(/* Sub-query for Andy */) AS Andy,(/* Sub-query for Betty */) AS Betty,(/*Sub-queries for the rest of participants */) AS Others FROM TableName GROUP BY Day
    
  4. 这很好用,但随着参与者数量的增加,查询字符串也会增长。我担心有一天查询变得比PHP的最大字符串长度长。我需要知道如何在MySQL中完全执行此操作。

1 个答案:

答案 0 :(得分:3)

SELECT  DAY,
        MAX(CASE WHEN Participant = 'Andy' THEN Score END) `Andy`,
        MAX(CASE WHEN Participant = 'Betty' THEN Score END) `Betty`,
        MAX(CASE WHEN Participant = 'Charlie' THEN Score END) `Charlie`
FROM    tableName
GROUP   BY DAY

如果您的参与者数量未知,则更好的方法是使用Dynamic SQL,例如

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(case when Participant = ''',
      Participant,
      ''' then Score end) AS ',
      Participant
    )
  ) INTO @sql
FROM TableName;

SET @sql = CONCAT('SELECT  DAY, ', @sql, ' 
                  FROM    tableName
                  GROUP   BY DAY');

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

输出

╔═════╦══════╦════════╦═════════╗
║ DAY ║ ANDY ║ BETTY  ║ CHARLIE ║
╠═════╬══════╬════════╬═════════╣
║ Mon ║    9 ║ 8      ║       7 ║
║ Tue ║    6 ║ 6      ║       8 ║
║ Wed ║    7 ║ (null) ║       4 ║
╚═════╩══════╩════════╩═════════╝