'MySQL - Rows to columns with strings

I've read this answer here, MySQL - Rows to Columns, and I've been able to apply it for my situation up until the aggregate function (Step 3).

I'm trying to convert the rows in itemname to columns for the rows in itemvalue in the following table:

+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
|      1 | address  | 12 street |
|      2 | email    | so@gmail  |
|      3 | name     | legend    |
+--------+----------+-----------+

I applied the following code:

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
);

And now I have the table_extended:

+--------+----------+-----------+-------------+----------+---------+
| hostid | itemname | itemvalue | address     | email    | name    |
+--------+----------+-----------+-------------+----------+---------+
|      1 | address  | 12 street |   12 street | NULL     | NULL    |
|      1 | email    | so@gmail  |        NULL | so@gmail | NULL    |
|      1 | name     | legend    |        NULL | NULL     | legend  |
+--------+----------+-----------+------+------+----------+---------+

In step 3 he uses sum to aggregate the extended table which all of the values are integers. I tried creating another view, with the following code, but of course these are strings so it turned all of rows except for hostid to 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
);

It looked like this:

+--------+-------------+----------+---------+
| hostid | address     | email    | name    |
+--------+-------------+----------+---------+
|      1 | 0           | 0        | 0       |
+--------+----------+-----------+------+----+

How can I consolidate all of the rows with NULL in order to get the following:

+--------+-------------+----------+---------+
| hostid | address     | email    | name    |
+--------+----------+-----------+-----------+
|      1 | 12 street   | so@gmail | legend  |
+--------+----------+-----------+------+----+


Solution 1:[1]

You can use the GROUP_CONCAT string function. This function tries to concatenate the strings matched on the GROUP BY clause and when encounters a NULL value, it just ignores it.

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

Here's a fiddle for double checking: https://www.db-fiddle.com/f/36M5CkwjWrzpdAc6qxyVx9/0.

Note: I've noticed that in your first reference of the table you have three different host ids while in the following one you're referencing only one host id. Are there some typos?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lemon