此刻我可能没有看清楚事情,但我在MySQL中有一个表格如下:
ID | a | b | c
1 | a1 | b1 | c1
2 | a2 | b2 | c2
由于某种原因(实际上是另一个表的连接 - 基于ID
,但我想如果有人可以帮我解决这个问题,我可以自己做其余的事情),我需要那些行就像相反:
1 | a1 | a
1 | b1 | b
1 | c1 | c
2 | a2 | a
2 | b2 | b
2 | c2 | c
基本上,我需要查看以下行:ID
,columntitle
,value
有没有办法轻松做到这一点?
答案 0 :(得分:20)
您正在尝试取消数据。 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
这也可以使用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
答案 1 :(得分:3)
尝试使用UNION ALL。
SELECT ID, a, 'a'
FROM tbl
WHERE ID = 1
UNION
SELECT ID, b, 'b'
FROM tbl
WHERE ID = 2
答案 2 :(得分:0)
这花了很长时间,但是MySQL 8.0.14版最终增加了对横向连接的支持-官方术语是lateral derived tables。
这是一项非常强大的功能,在多种情况下都非常方便,包括将表中的列移到行中。
您可以按如下方式查询查询:
function waitBeforeAttempt() {
const start = new Date();
let now;
while (true) {
now = new Date();
if (now - start >= 15000) {
break;
}
}
}
与典型的规范解决方案相比,这似乎没有太大区别-毕竟,我们仍在横向派生表中使用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)
……但请不要误解:此查询仅扫描表一次,而另一种方法则需要对每一列进行一次扫描才能取消透视。因此,这种方法效率更高-随着表格变大和/或需要取消旋转更多列,性能提升将大大提高。
底线:如果您正在运行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添加了对the VALUES
statement的支持,这可以通过消除在子查询中使用union all
的需要来帮助进一步缩短查询(尽管我在这里看不到任何性能提升,但这使查询更整洁。)
不幸的是,从8.0.21版开始,此无效-可能被认为是错误-但在将来的版本中可能会...:
union all