MySQL - 带字符串的行到列

Abd*_*eed 6 mysql sql

我在这里阅读了这个答案,MySQL - Rows to Columns,并且我已经能够将其应用于我的情况,直到聚合函数(步骤3)。

我正在尝试将下表itemname中的行转换为列:itemvalue

主机ID 项目名 项目值
1 地址 12街
2 电子邮件 所以@gmail
3 姓名 传奇

我应用了以下代码:

create view table_extended as (
  select
    history.*,
    case when itemname = "address" then itemvalue end as address,
    case when itemname = "email" then itemvalue end as email,
    case when itemname = "name" then itemvalue end as name
  from history
);
Run Code Online (Sandbox Code Playgroud)

现在我有了table_extended:

主机ID 项目名 项目值 地址 电子邮件 姓名
1 地址 12街 12街 无效的 无效的
1 电子邮件 所以@gmail 无效的 所以@gmail 无效的
1 姓名 传奇 无效的 无效的 传奇

在步骤 3中,他使用sum聚合扩展表,其中所有值都是整数。我尝试使用以下代码创建另一个视图,但当然这些是字符串,因此它将除 hostid 之外的所有行都变为 0。

create view history_itemvalue_pivot as (
  select
    hostid,
    sum(address) as address,
    sum(email) as email,
    sum(name) as name
  from history_extended
  group by hostid
);
Run Code Online (Sandbox Code Playgroud)

它看起来像这样:

主机ID 地址 电子邮件 姓名
1 0 0 0

如何合并所有行NULL以获得以下内容:

主机ID 地址 电子邮件 姓名
1 12街 所以@gmail 传奇

lem*_*mon 1

您可以使用GROUP_CONCAT字符串函数。该函数尝试连接子句中匹配的字符串GROUP BY,当遇到一个NULL值时,它会忽略它。

SELECT hostid,
       GROUP_CONCAT(address)    AS address,
       GROUP_CONCAT(email)  AS email,
       GROUP_CONCAT(name)       AS name
FROM (SELECT history.*,
             CASE WHEN itemname = "address" THEN itemvalue END AS address,
             CASE WHEN itemname = "email" THEN itemvalue END AS email,
             CASE WHEN itemname = "name" THEN itemvalue END AS name
      FROM history
) history_extended
GROUP BY hostid
Run Code Online (Sandbox Code Playgroud)

在这里查看演示。

注意:我注意到,在您对该表的第一次引用中,您有三个不同的主机 ID,而在接下来的引用中,您仅引用了一个主机 ID。有一些错别字吗?