Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL - How to unpivot columns to rows?

I'm probably not seeing things very clear at this moment, but I have a table in MySQL which looks like this:

ID | a  | b  | c 
1  | a1 | b1 | c1
2  | a2 | b2 | c2

For some reason (actually a join on another table - based on ID, but I think if someone can help me out with this part, I can do the rest myself), I needed those rows to be like this instead:

1 | a1 | a
1 | b1 | b
1 | c1 | c
2 | a2 | a
2 | b2 | b
2 | c2 | c

So basically, I need to view the rows like: ID, columntitle, value Is there any way to do this easily?

like image 756
user2128539 Avatar asked Mar 03 '13 09:03

user2128539


People also ask

How do I make a column into a row in MySQL?

What you need to do is first, unpivot the data and then pivot it. But unfortunately MySQL does not have these functions so you will need to replicate them using a UNION ALL query for the unpivot and an aggregate function with a CASE for the pivot.

What is Unpivot in MySQL?

UNPIVOT is a relational operator that accepts two columns (from a table or subquery), along with a list of columns, and generates a row for each column specified in the list. In a query, it is specified in the FROM clause after the table name or subquery.

Does MySQL have Unpivot?

Since MySQL doesn't offer an UNPIVOT function, You need to use UNION ALL clause in to reverse pivot a table in MySQL. In the above query, we basically cut the original table into 3 smaller ones – one for each column a,b,c and then append them one below the other using UNION ALL.

How do I Unpivot columns?

For more information see Create, load, or edit a query in Excel. Select the columns you do want to unpivot. To select more than one column contiguously or discontiguously, press Shift+Click or CTRL+Click on each subsequent column. Select Transform > Unpivot Only Selected Columns.

How to UNPIVOT table in MySQL?

Since MySQL doesn’t have a function to UNPIVOT or REVERSE PIVOT a table, you need to write a SQL query to transpose columns into rows. Here’s how to unpivot table in MySQL.

What is UNPIVOT data in Excel?

In Excel, unpivot data means to transform your data from columns to rows, where column headings are one row and the rows of data below the columns become their own separate, combined row. It provides a new way for viewing data, particularly numerical data, and its association with different column headings.

How to convert column names into row values in SQL Server?

The SQL Unpivot is one of the most useful Operators to convert the Column names into Row values. Or say, Rotating Pivot table to regular table. Let us see how to convert Column names into Row values using Unpivot in SQL Server with example.

Why can't I combine multiple values in a pivot table?

The reason is, Pivot performs aggregation while rotating row values into column values and might merge possible multiple row values into single column value in the output. For example, consider for a given country and year there are two values, say 5000 and 6000.


3 Answers

You are trying to unpivot the data. MySQL does not have an unpivot function, so you will have to use a UNION ALL query to convert the columns into rows:

select id, 'a' col, a value
from yourtable
union all
select id, 'b' col, b value
from yourtable
union all
select id, 'c' col, c value
from yourtable

See SQL Fiddle with Demo.

This can also be done using a CROSS JOIN:

select t.id,
  c.col,
  case c.col
    when 'a' then a
    when 'b' then b
    when 'c' then c
  end as data
from yourtable t
cross join
(
  select 'a' as col
  union all select 'b'
  union all select 'c'
) c

See SQL Fiddle with Demo

like image 143
Taryn Avatar answered Oct 14 '22 07:10

Taryn


Try to use UNION ALL.

SELECT ID, a, 'a' 
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b' 
FROM tbl
WHERE ID = 2
like image 38
Iswanto San Avatar answered Oct 14 '22 08:10

Iswanto San


It took a long time coming, but MySQL version 8.0.14 finally added support for lateral joins - the official terminology is lateral derived tables.

This is a very powerful feature, that comes handy in multiple situations, including unpivoting table columns to rows.

You can phrase the query as follows:

select t.id, x.*
from mytable t
cross join lateral (
    select a, 'a' 
    union all select b, 'b'
    union all select c, 'c'
) as x(col1, col2)

It may look like this is not a big difference compared to the typical cannonical solution - after all, we are still using union all within the lateral derived table... But don't get it wrong: this query scans the table only once, as opposed to the other approach, which requires one scan for each column to unpivot. So this is more efficient - and the performance gain increases dramatically as the table goes bigger and/or more columns need to be unpivoted.

Bottom line: if you are running MySQL 8.0.14 or higher, just use this technique. From that version onwards, this is the canonical way to unpivot in MYSQL.

Demo on DB Fiddle:

Sample data:

ID | a  | b  | c 
-: | :- | :- | :-
 1 | a1 | b1 | c1
 2 | a2 | b2 | c2

Query results:

id | col1 | col2
-: | :--- | :---
 1 | a1   | a   
 1 | b1   | b   
 1 | c1   | c   
 2 | a2   | a   
 2 | b2   | b   
 2 | c2   | c   

Side note

MySQL 8.0.19 added support for the VALUES statement, which could help further shortening the query by removing the need to use union all in a subquery (although I don't see any performance gain here, this makes the query neater).

nfortunately, As of version 8.0.21, this does not work yet - which might be considered a bug - but maybe will in a future version...:

select t.id, x.*
from mytable t
cross join lateral (values 
    row(a, 'a'), 
    row(b, 'b'),
    row(c, 'c')
) as x(col1, col2);
like image 38
GMB Avatar answered Oct 14 '22 07:10

GMB