MySQL-如何将列解压到行?

MySQL-如何将列解压到行?,mysql,sql,union,unpivot,lateral-join,Mysql,Sql,Union,Unpivot,Lateral Join,我现在可能看不太清楚,但我在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,columnti

我现在可能看不太清楚,但我在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
有什么方法可以轻松做到这一点吗?

尝试使用

您正在尝试取消填充数据。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

这也可以使用交叉连接来完成:

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最终增加了对横向连接的支持——官方术语是

这是一个非常强大的功能,在多种情况下都很方便,包括取消表列到行的驱动

您可以按如下方式表达查询:

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)
与典型的cannonical解决方案相比,这似乎没有太大的区别-毕竟,我们仍然在侧向衍生表中使用
union all
。。。但是不要弄错了:这个查询只扫描表一次,而另一种方法需要对每一列进行一次扫描才能取消PIVOT。因此,这样做效率更高,而且随着表变大和/或需要取消插入更多列,性能增益会显著增加

一句话:如果您正在运行MySQL 8.0.14或更高版本,只需使用此技术。从那个版本开始,这是在MYSQL中取消PIVOT的标准方法

样本数据:

ID | a | b | c -: | :- | :- | :- 1 | a1 | b1 | c1 2 | a2 | b2 | c2
你的意思是“ID,value,columntitle”?是的,但是顺序并不重要,只要行是ID-columntitle-values谢谢。所以看来根本没有一条真正的捷径(这是相当多的列,我认为对于每一列都有一种比“select…from…”更简单的方法。@user2128539查看我的编辑,我包括了一种不同的方法来解除数据的隐藏。@user2128539您应该接受解决问题的答案。救生员回答摆脱
WHERE
子句。否则,您只显示一列。)每个ID的umn,而不是每个ID的所有列。 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
select t.id, x.*
from mytable t
cross join lateral (values 
    row(a, 'a'), 
    row(b, 'b'),
    row(c, 'c')
) as x(col1, col2);