MySQL - 将表转换为不同的表

use*_*539 18 mysql unpivot

我现在可能没有看清楚事情,但我在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)

请参阅SQL Fiddle with Demo.

这也可以使用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)

请参阅SQL Fiddle with Demo


GMB*_*GMB 8

等了很长时间,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 中逆透视的规范方法。

DB Fiddle 演示

样本数据:

身份证 | 一个 | 乙| 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)


Isw*_*San 3

尝试使用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)