我现在可能没有看清楚事情,但我在MySQL中有一个表,如下所示:
ID | a | b | c
1 | a1 | b1 | c1
2 | a2 | b2 | c2
Run Code Online (Sandbox Code Playgroud)
出于某种原因(实际上是在另一个表上加入 - 基于ID,但我想如果有人可以帮我解决这个问题,我可以自己做其余的事情),我需要那些行代替:
1 | a1 | a
1 | b1 | b
1 | c1 | c
2 | a2 | a
2 | b2 | b
2 | c2 | c
Run Code Online (Sandbox Code Playgroud)
所以基本上,我需要查看,如行: ID,columntitle,value
有没有什么办法可以轻松地做到这一点?
Tar*_*ryn 21
您正试图取消数据.MySQL没有unpivot函数,因此您必须使用UNION ALL查询将列转换为行:
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
Run Code Online (Sandbox Code Playgroud)
这也可以使用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
Run Code Online (Sandbox Code Playgroud)
等了很长时间,MySQL 8.0.14 版本终于添加了对横向连接的支持——官方术语是横向派生表。
这是一个非常强大的功能,在多种情况下都很方便,包括将表列反转为行。
您可以按如下方式表达查询:
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)
Run Code Online (Sandbox Code Playgroud)
与典型的规范解决方案相比,这可能看起来并没有太大区别 - 毕竟,我们仍在union all横向派生表中使用......但不要误解:此查询仅扫描表一次,而不是另一种方法需要对每列进行一次扫描才能取消透视。因此,这更加高效 - 并且随着表变大和/或需要取消透视更多列,性能增益会显着增加。
底线:如果您运行的是 MySQL 8.0.14 或更高版本,则只需使用此技术即可。从该版本开始,这是 MYSQL 中逆透视的规范方法。
样本数据:
身份证 | 一个 | 乙| C -: | :- | :- | :- 1 | a1 | b1 | c1 2 | a2 | b2 | c2
查询结果:
编号 | 第 1 列 | 列2 -: | :--- | :--- 1 | a1 | A 1 | b1 | 乙 1 | c1 | C 2 | a2 | A 2 | b2 | 乙 2 | c2 | C
更新
MySQL 8.0.19 首先引入了对 statements 的支持,VALUES这可以通过消除在子查询中使用的需要来帮助进一步缩短查询union all(虽然我在这里没有看到任何性能提升,但这使得查询更整洁)。从版本 8.0.30 开始,我们可以像这样表达横向连接:
select t.id, x.*
from mytable t
cross join lateral (values
row(a, 'a'),
row(b, 'b'),
row(c, 'c')
) as x(col1, col2);
Run Code Online (Sandbox Code Playgroud)
尝试使用UNION ALL。
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15885 次 |
| 最近记录: |