我目前有一个以下表格的表格
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数据透视表。这甚至可能吗?
答案 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:
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
上的会话设置。