MySQL:将单行显示为列(简单地说,通过 SELECT)

Posted

技术标签:

【中文标题】MySQL:将单行显示为列(简单地说,通过 SELECT)【英文标题】:MySQL: Display single row as column (simply, via SELECT) 【发布时间】:2020-10-05 19:54:23 【问题描述】:

是否有一种简单的方法可以在 mysql 中选择单行并将其转置,以便列标题列在左侧列中,值列在右侧列中?

例子:

而不是这个:

SELECT * FROM sock_table LIMIT 1;

+---------+--------------+------------+
| sock_id | smell_factor | hole_count | 
+---------+--------------+------------+
| S000123 | 7.2          | 1          |
+---------+--------------+------------+

...你可以这样做:

SELECT TRANSPOSE(*) FROM sock_table LIMIT 1;

sock_id      S000123
smell_factor     7.2
hole_count         1

对于熟悉python-pandas的朋友,df.loc[0](其中0是索引位置)会自动执行这个功能。

这适用于具有数十个列标题的表格,因此输入标题比它的价值更麻烦。

【问题讨论】:

对每列使用 UNION 的查询。 没有任何内置功能可以做到这一点。 刚刚更新了我的问题,指出输入列名会破坏目的。也许@Barmar 是对的:缺乏原生功能。 如果您不想为每列键入所有子查询,您可以创建一个存储过程,从INFORMATION_SCHEMA.COLUMNS 表中生成动态 SQL。 【参考方案1】:

在 MYSQL 中,使用UNION ALL 进行反透视:

(select 'stock_id' col, stock_id val FROM stock_table order by id limit 1)
union all (select 'smell_factor' col, smell_factor val FROM stock_table order by id limit 1)
union all (select 'hole_count' col, hole_count val FROM stock_table order by id limit 1)

重要提示:

这需要每列一个子查询

LIMIT 没有ORDER BY 是不稳定的;您需要一个确定性的 ORDER BY 子句 - 我假设列 id 可用于对记录进行排序

值的数据类型需要保持一致 - 如果不是这种情况,您可能需要 cast 它们


编辑

实际上,最新版本的 MySQL(8.0.19 或更高版本)可以使用 values row()lateral 来表达这一点,从而缩短查询:

select x.* 
from (select * from mytable order by id limit 1) t,
lateral (values
    row ('stock_id', t.stock_id), 
    row ('smell_factor', t.smell_factor),
    row ('hole_count', t.hole_count)
) x(col, val)

【讨论】:

感谢您发布 GMB,但我的问题中的示例表过于简单,它将包含更多列。 @elPastor:所以您需要更多union all 成员(每列一个)。 哎呀,好的。听起来果汁不值得挤。无论如何,再次感谢。 @elPastor:如果您运行的是 MySQL 8.0.14 或更高版本,请参阅我的编辑以获取替代方案。 谢谢,但同样,我必须输入几十列,我正在寻找一个简单的函数,我猜它不存在。【参考方案2】:

假设sock_table由这三列组成,sock_id作为表的主键,以便在ORDER BY子句中使用。然后,考虑使用此动态查询语句以获得非透视结果:

SET @sql = NULL;
       
SELECT GROUP_CONCAT(
       CONCAT( 
       '( SELECT "',column_name,'" AS col_name, ',column_name,' AS value 
            FROM ',table_name,' ORDER BY sock_id LIMIT 1 ) ' )
       SEPARATOR 'UNION ALL ')
  INTO @sql     
  FROM information_schema.columns c
 WHERE table_name = 'sock_table'
 ORDER BY ordinal_position;      


PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt; 

Demo

这种情况下,不需要单独指定每个列名。

【讨论】:

以上是关于MySQL:将单行显示为列(简单地说,通过 SELECT)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL - 将行显示为列(尽可能简单)

如何将mysql行转换为列的简单方法

如何在 MySQL 中将行数据转置为列

如何将mysql行以简单的方式转换为列

将Dataframe Pivot折叠为单行

Mysql查询根据两列动态将行转换为列