ID | a | b | c
1 | a1 | b1 | c1
2 | a2 | b2 | c2
我该如何将行重新组织为ID
、columntitle
和value
?
1 | a1 | a
1 | b1 | b
1 | c1 | c
2 | a2 | a
2 | b2 | b
2 | c2 | c
ID | a | b | c
1 | a1 | b1 | c1
2 | a2 | b2 | c2
我该如何将行重新组织为ID
、columntitle
和value
?
1 | a1 | a
1 | b1 | b
1 | c1 | c
2 | a2 | a
2 | b2 | b
2 | c2 | c
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
请参见带演示的SQL Fiddle。
这也可以使用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
经过漫长等待,MySQL 8.0.14 版本终于添加了支持 Lateral Join - 官方术语是 lateral derived tables。
这是一个非常强大的功能,在多种情况下非常方便实用,包括将表列转换为行。
您可以按如下方式构造查询:
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)
这看起来与典型的规范解决方案相比并没有太大的区别 - 毕竟,我们仍然在侧向派生表中使用union all
... 但不要误解:这个查询只扫描了一次表,而另一种方法需要为每个列进行一次扫描以进行反转。因此,这更有效率 - 随着表格变得更大和/或需要反转的列数增加,性能收益会显著提高。
底线:如果您正在运行MySQL 8.0.14或更高版本,请使用此技术。从该版本开始,这是MYSQL中反转的规范方式。
样本数据:
ID | a | b | c -: | :- | :- | :- 1 | a1 | b1 | c1 2 | a2 | b2 | c2
查询结果:
id | col1 | col2 -: | :--- | :--- 1 | a1 | a 1 | b1 | b 1 | c1 | c 2 | a2 | a 2 | b2 | b 2 | c2 | c更新
MySQL 8.0.19首次引入了VALUES
语句的支持,这可以通过在子查询中删除使用union all
来进一步缩短查询(虽然我在这里没有看到任何性能提升,但这使查询更加整洁)。从版本8.0.30开始,我们可以这样表达lateral join:
select t.id, x.*
from mytable t
cross join lateral (values
row(a, 'a'),
row(b, 'b'),
row(c, 'c')
) as x(col1, col2);
尝试使用UNION ALL。
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
WHERE
子句。否则,您只会为每个ID显示一个列,而不是每个ID的所有列。 - Barmar