mysql选择动态行值作为列名,另一列作为值

Posted

技术标签:

【中文标题】mysql选择动态行值作为列名,另一列作为值【英文标题】:mysql select dynamic row values as column names, another column as value 【发布时间】:2012-06-11 03:09:37 【问题描述】:

我有一个旧的用户信息表(仍在使用中),我无法更改 -

id    name       value
------------------------------
0     timezone   Europe/London
0     language   en
0     country    45
0     something  x
1     timezone   Europe/Paris
1     language   fr
1     country    46

时区/语言/国家等只是名称的示例,它们可以是可变的/除了该列的行上唯一之外没有有限列表

我需要一个与 mysql 兼容的 SQL 查询,它会返回 -

id    timezone       language    country  something
---------------------------------------------------
0     Europe/London  en          45       x
1     Europe/Paris   fr          46

我已经查看了有关将数据透视表功能入侵到 MySQL 的 *** 上的各种答案,类似但没有一个似乎与使用来自同一表列的唯一行值的变量列名别名的情况相匹配。虽然我睡得很少,所以他们都开始变得有点模糊,提前道歉。

我能找到的最接近的方法是使用准备好的语句https://***.com/a/986088/830171,它首先从名称列中获取所有可能/唯一的值,并构建一个使用CASE WHEN 和/或多个子SELECT 或@987654326 的查询@ 在同一个表查询上。

我能想到的替代方法是获取该用户 ID 的所有行并在应用程序本身中在 for 循环中处理它们,或者尝试将名称限制为有限数量并使用 sub-SELECTs /JOINs。但是,如果添加了新名称,则第二个选项并不理想,我必须重新访问此查询。

请告诉我我遗漏了一些明显的东西

【问题讨论】:

您真的需要在sql 中表达这一点,还是使用您选择的编程语言进行后处理就足够了?如果你需要加入你的去伪数据,那么视图/过程可能是诀窍。 是的,我暂时将混乱保留在应用程序级别 - 我将获取该用户 ID 的所有行并循环将数据放入关联数组中。我只是想检查一下这是唯一的好选择。使用 SQL 方法进行迁移和一次性报告仍然非常方便。 【参考方案1】:

与其他一些 RDBMS 不同,MySQL 按设计不原生支持此类旋转操作(开发人员认为它更适合应用程序的表示层,而不是数据库层)。

如果您绝对必须在 MySQL 中执行此类操作,那么构建一个准备好的语句是可行的方法——尽管我不会乱用 CASE,我可能只使用 MySQL 的 GROUP_CONCAT() 函数:

SELECT CONCAT(
  'SELECT `table`.id', GROUP_CONCAT('
     ,    `t_', REPLACE(name, '`', '``'), '`.value
         AS `', REPLACE(name, '`', '``'), '`'
     SEPARATOR ''),
 ' FROM `table` ', GROUP_CONCAT('
     LEFT JOIN `table`   AS `t_', REPLACE(name, '`', '``'), '`
            ON `table`.id = `t_', REPLACE(name, '`', '``'), '`.id
           AND `t_', REPLACE(name, '`', '``'), '`.name = ', QUOTE(name)
     SEPARATOR ''),
 ' GROUP BY `table`.id'
) INTO @qry FROM (SELECT DISTINCT name FROM `table`) t;

PREPARE stmt FROM @qry;
EXECUTE stmt;

在sqlfiddle 上查看。

请注意,GROUP_CONCAT() 的结果受 group_concat_max_len 变量的限制(默认为 1024 字节:在这里不太可能相关,除非您有一些非常长的 name 值)。

【讨论】:

哇 - 感谢您付出所有努力编写和测试解决方案。非常感激。我一直想知道如何进行这种类型的查询,它看起来和我想象的一样复杂。现在,我将保持应用程序级别的混乱,但是这个查询对于报告和迁移仍然非常方便。谢谢。 我有一个非常相似的场景,使用您的出色示例,我可以正常显示旋转结果。但是我需要将结果存储在表格中,因为我想从中生成图表。是否可以将透视结果存储到表中?另外,是否可以在 php 中执行上述操作?我的源表是用户、日期、性能和数据透视表是用户作为行,日期作为列,性能作为单元格值。 已将我的示例表放在 sqlfiddle 上(请参阅sqlfiddle.com/#!2/06be4/1) 做得很好,上面的查询帮助我更正并扩展了我正在处理的查询。谢谢!

以上是关于mysql选择动态行值作为列名,另一列作为值的主要内容,如果未能解决你的问题,请参考以下文章

通过特定行值动态获取列名

动态生成列名时如何获取kendo选择的行值

Pyspark:用同名的另一列替换行值

以列名作为输入参数的存储过程中的动态 sql

Mysql - 通过引用另一个数据集动态更改列名

Oracle PL/SQL - 循环值作为没有动态 SQL 的动态列名