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?
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.
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.
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.
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.
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.
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.
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.
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.
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
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With