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?
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
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).
Unfortunately, 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);
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
Related
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?
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
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).
Unfortunately, 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);
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
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?
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
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).
Unfortunately, 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);
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
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?
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
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).
Unfortunately, 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);
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
Simple problem. Given example tables:
Table A:
id | type
---+-----
1 | A
2 | B
3 | C
Table B:
id | a_id | type
---+------+-----
1 | 1 | X
2 | 2 | Y
3 | 1 | X
4 | 3 | Z
(there are additional columns, which I omitted, in order to clarify the problem)
The query:
SELECT a.*
FROM a a
INNER JOIN b b ON b.a_id = a.id
WHERE b.type = 'X'
Result:
id | type
---+-----
1 | A
1 | A
SQL Fiddle: http://sqlfiddle.com/#!2/e6138f/1
But I only want to have distinct rows of Table A. I know, I could do SELECT DISTINCT a.*, but our Table A has about 40 columns, and this SELECT can return 100-10000 rows. Isn't that extremely slow, if the database has to compare each column?
Or is MySQL intelligent enough, to just focus on the Primary Key for the DISTINCT operation?
Thanks in advance :)
Use exists instead of an explicit join:
select a.*
from tablea a
where exists (select 1 from tableb b where b.a_id = a.id and b.type = 'x');
For performance, create an index on tableb(a_id, type).
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?
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
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).
Unfortunately, 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);
Try to use UNION ALL.
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2