MySQL:将单行显示为列(只需通过选择)
有没有一种简单的方法可以选择MySQL中的一行并将其转置,以便列标题列在左侧列中,值列在右侧列中 例如: 与此相反:MySQL:将单行显示为列(只需通过选择),mysql,sql,unpivot,Mysql,Sql,Unpivot,有没有一种简单的方法可以选择MySQL中的一行并将其转置,以便列标题列在左侧列中,值列在右侧列中 例如: 与此相反: SELECT * FROM sock_table LIMIT 1; +---------+--------------+------------+ | sock_id | smell_factor | hole_count | +---------+--------------+------------+ | S000123 | 7.2 | 1
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是索引位置
这将适用于一个有几十个列标题的表,因此键入标题是一件非常麻烦的事情。在MYSQL中,使用UNION ALL取消PIVOT:
(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)
重要提示:
这要求每列有一个子查询
没有订单的限制是不稳定的;您需要一个确定的ORDERBY子句——我假设可以使用列id对记录进行排序
值的数据类型需要一致——如果不是这样,您可能需要强制转换它们
编辑
事实上,MySQL 8.0.19或更高版本的最新版本可以使用row和LATENAL值来表示这一点,从而缩短了查询:
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)
在MYSQL中,使用UNION ALL取消PIVOT:
(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)
重要提示:
这要求每列有一个子查询
没有订单的限制是不稳定的;您需要一个确定的ORDERBY子句——我假设可以使用列id对记录进行排序
值的数据类型需要一致——如果不是这样,您可能需要强制转换它们
编辑
事实上,MySQL 8.0.19或更高版本的最新版本可以使用row和LATENAL值来表示这一点,从而缩短了查询:
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)
假设sock_表由这三列组成,sock_id作为表的主键,以便在orderby子句中使用。然后,考虑使用这个动态查询语句,以获得未枢转的结果:
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;
在这种情况下,不需要单独指定每个列名。假设sock_表由这三列组成,并且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;
在这种情况下,不需要单独指定每个列名。对每个列使用联合查询。没有内置的功能可以做到这一点。只是更新了我的问题,指出键入列名将无法达到此目的。也许@Barmar是对的,因为缺少本机功能。如果您不想为每个列键入所有子查询,您可以创建一个存储过程,从INFORMATION_SCHEMA.COLUMNS表生成动态SQL。对每一列使用联合查询。没有内置的方法可以做到这一点。只是更新了我的问题,指出键入列名将无法达到此目的。也许@Barmar是对的,因为缺少本机功能。如果您不想为每个列键入所有子查询,您可以创建一个存储过程,从INFORMATION_SCHEMA.COLUMNS表生成动态SQL。感谢发布GMB,但我问题中的示例表过于简化,它将有更多的栏。@elPastor:所以你需要更多的联合所有成员,每个栏一个。Eeesh,好的。听起来这果汁不值得挤。无论如何,再次感谢。@elPastor:如果您运行的是MySQL 8.0.14或更高版本,请参阅我的编辑以获得替代方案。谢谢,但再次感谢,我必须键入几十列,我正在寻找一个简单的函数,我猜它不存在。感谢发布GMB,但我问题中的示例表过于简单,它将有更多的栏。@elPastor:所以你需要更多的联合所有成员,每个栏一个。Eeesh,好的。听起来这果汁不值得挤。无论如何,再次感谢。@elPastor:如果您运行的是MySQL 8.0.14或更高版本,请参阅我的编辑以获得替代方案。谢谢,但再次感谢,我必须键入几十列,我正在寻找一个简单的函数,我猜它不存在。