简体   繁体   中英

How to get a pivot-table like result using MySQL

Assume we have a table in mysql:test;
how to get a result table like the pivot table in excel?

Tried to use "merge" but mysql does not support it.

Tried to use "union" but it's the index that increases but not the column.

select * from test;

Output

+----+------------+------+-------+
| id | date       | name | value |
+----+------------+------+-------+
|  1 | 2019-01-01 | a    |     1 |
|  2 | 2019-01-02 | a    |     2 |
|  3 | 2019-01-03 | a    |     3 |
|  4 | 2019-01-04 | a    |     4 |
|  5 | 2019-01-05 | a    |     5 |
|  6 | 2019-01-06 | a    |     6 |
|  7 | 2019-01-03 | b    |     9 |
|  8 | 2019-01-04 | b    |     9 |
|  9 | 2019-01-05 | b    |     8 |
| 10 | 2019-01-06 | b    |     7 |
| 11 | 2019-01-05 | c    |     5 |
| 12 | 2019-01-06 | c    |     6 |
| 13 | 2019-01-07 | c    |     7 |
| 14 | 2019-01-08 | c    |     8 |
| 15 | 2019-01-09 | c    |     9 |
+----+------------+------+-------+

Wanted to get:

+------------+---+---+---+
| date       | a | b | c |
+------------+---+---+---+
| 2019-01-01 | 1 |   |   |
| 2019-01-02 | 2 |   |   |
| 2019-01-03 | 3 | 9 |   |
| 2019-01-04 | 4 | 9 |   |
| 2019-01-05 | 5 | 8 | 5 |
| 2019-01-06 | 6 | 7 | 6 |
| 2019-01-07 |   |   | 7 |
| 2019-01-08 |   |   | 8 |
| 2019-01-09 |   |   | 9 |
+------------+---+---+---+

I know it's very easy to get the result in Excel, but how to use SQL?

Edit:

A followed question.

What if I do NOT know what are the names in the column "name"?

That is to say, there may be a,b,c,d,e,f,g...but I do NOT know how many of distinct names are there.

How to get the result by listing all of them? ()

+------------+---+---+---+
| date       | a | b | c |...... and so on.
+------------+---+---+---+

You can use CASE with GROUP_CONCAT to get the desired output. And good practice is to avoid reserved words like name , date , value

SELECT date,
GROUP_CONCAT(CASE WHEN name='a' THEN value END) as 'a', 
GROUP_CONCAT(CASE WHEN name='b' THEN value END) as 'b', 
GROUP_CONCAT(CASE WHEN name='c' THEN value END) as 'c' 
FROM test GROUP BY `date`;

Edit: It can be achieved by creating a dynamic query using prepared statement .

Since value to be summed for a column in a specific date, Sharing the query with SUM . You can replace with GROUP_CONCAT if needed.

SELECT 
GROUP_CONCAT(CONCAT(" SUM(CASE WHEN name='",name,"' THEN value END) AS '",name,"'")) 
INTO @pivotcol
FROM (SELECT `name` FROM test GROUP BY `name`) t;

SET @pivotquery =CONCAT("SELECT date, ",@pivotcol," from test GROUP BY `date`");

PREPARE stmt FROM @pivotquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM