简体   繁体   English

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

[英]mysql select dynamic row values as column names, another column as value

I have a legacy table of user information (that is still in active use) and I cannot change the structure of - 我有一个旧的用户信息表(仍在使用中),并且不能更改-

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

timezone/language/country etc are only examples of names, they can be variable/there is no finite list other than unique on rows of that column 时区/语言/国家等只是名称的示例,它们可以是可变的/除了该列的行上的唯一列表外,没有其他任何有限列表

I need a MySQL compatible SQL query that would return - 我需要一个MySQL兼容的SQL查询,该查询将返回-

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

I've looked through various answers on stackoverflow around hacking Pivot table functionality in to MySQL, and similar but none of them seem to match this case of using variable column name alias from unique row values from a column of the same table. 我已经研究了关于将数据透视表功能窃取到MySQL的关于stackoverflow的各种答案,并且类似,但是它们似乎都与使用相同表的唯一行值中的可变列名别名的情况不匹配。 Although I have had little sleep so they're all starting to become a bit of a blur, apologies in advance. 尽管我几乎没有睡觉,所以他们都开始变得有点模糊,但要提前道歉。

Closest I could find would be to use prepared statements https://stackoverflow.com/a/986088/830171 which would first get all possible/unique values from name column and build a query that uses CASE WHEN , and/or multiple sub- SELECT or JOIN on same table queries. 我能找到的最接近的是使用准备好的语句https://stackoverflow.com/a/986088/830171 ,该语句首先会从名称列中获取所有可能的/唯一的值,并建立使用CASE WHEN和/或多个子CASE WHEN的查询在同一表查询上执行SELECTJOIN

The alternatives I can think of would be to get all rows for that user id and process them in the application itself in a for-loop, or attempt to limit the names to a finite amount and use sub- SELECT s/ JOIN s. 我能想到的替代将得到所有行该用户ID和一个for循环处理它们在应用程序本身,或尝试将名称限制在一个有限的数量和使用的子SELECT S / JOIN秒。 However that second option is not ideal if a new name is added I'd have to revisit this query. 但是,如果添加了新名称,则第二个选项并不理想,我将不得不重新访问该查询。

Please tell me I've missed something obvious 请告诉我我错过了明显的事情

Unlike some other RDBMS MySQL doesn't have native support for pivoting operations of this sort by design (the developers feel it's more suited to the presentation, rather than database, layer of your application). 与某些其他RDBMS不同,MySQL不原生支持按设计进行此类透视操作(开发人员认为它更适合应用程序的表示层而不是数据库层)。

If you absolutely must perfom such manipulations within MySQL, building a prepared statement is the way to go—although rather than messing around with CASE , I'd probably just use MySQL's GROUP_CONCAT() function: 如果您绝对必须在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;

See it on sqlfiddle . sqlfiddle上看到它。

Note that the result of GROUP_CONCAT() is limited by the group_concat_max_len variable (default of 1024 bytes: unlikely to be relevant here unless you have some extremely long name values). 请注意, GROUP_CONCAT()的结果受group_concat_max_len变量限制(默认为1024字节:除非您有一些非常长的name值,否则此处不太可能相关)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM