0

我目前有以下表格的表格

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
.
.
.

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

4

1 回答 1

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如果您的字符串太长,您可能需要更改会话设置。

于 2013-04-08T14:57:37.190 回答