MySQL数据透视表和直方图同时出现

时间:2013-04-08 14:52:19

标签: mysql pivot

我目前有一个以下表格的表格

account_id | phone_name
0          | samsung M360
12         | HTC One
58         | LG Optimus
12         | Novatel
.            .
.            .
.            .

我希望将其转换为以下格式的表格

account_id | samsung M360 | HTC One | LG Optimus | Novatel | ...
0            1              0         0            0
12           0              1         0            1
58           0              0         1            0
.
.
.

即。我想制作一个数据透视表,其中包含每个account_id的phone_names计数。主要的问题是有50多个不同的电话名称,所以我不能通过列出每个phone_name以通常的方式做一个MySQL数据透视表。这甚至可能吗?

1 个答案:

答案 0 :(得分:1)

MySQL没有PIVOT函数,但您可以使用带有CASE表达式的聚合函数将行转换为列。

如果您的数字有限或phone_name,那么您可以对查询进行硬编码:

select account_id,
  sum(case when phone_name = 'samsung M360' then 1 else 0 end) SamsungM360,
  sum(case when phone_name = 'HTC One' then 1 else 0 end) HTCOne,
  sum(case when phone_name = 'LG Optimus' then 1 else 0 end) LGOptimus,
  sum(case when phone_name = 'Novatel' then 1 else 0 end) Novatel
from yt
group by account_id;

请参阅SQL Fiddle with Demo

但是如果值是未知的,那么您将需要使用预准备语句来生成动态SQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN phone_name = ''',
      phone_name,
      ''' THEN 1 else 0 END) AS `',
      phone_name, '`'
    )
  ) INTO @sql
FROM yt;

SET @sql 
  = CONCAT('SELECT account_id, ', @sql, ' 
            from yt
            group by account_id');

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

SQL Fiddle with Demo。两个查询都给出了结果:

| ACCOUNT_ID | SAMSUNG M360 | HTC ONE | LG OPTIMUS | NOVATEL |
--------------------------------------------------------------
|          0 |            1 |       0 |          0 |       0 |
|         12 |            0 |       1 |          0 |       1 |
|         58 |            0 |       0 |          1 |       0 |

注意:GROUP_CONCAT()的默认值为1024,即生成的字符串的长度。因此,如果字符串太长,您可能需要更改group_concat_max_length上的会话设置。