mysqlselectdynamic行值作为列名,另一列作为值
我有一个遗留的用户信息表(这仍然在积极使用),我不能改变的结构 –
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
我已经通过各种各样的解决scheme,看看围绕黑客入侵MySQL的数据透视表function,以及类似的,但没有一个似乎匹配这种情况下从同一个表的列中的唯一行值使用variables列名别名。 虽然我几乎没有睡觉,所以他们都开始变得模糊,提前道歉。
最近我可以find将使用预先准备的语句https://stackoverflow.com/a/986088/830171这将首先从名称列中获取所有可能的/唯一的值,并build立使用CASE WHEN
,和/或多个子查询的查询, SELECT
或JOIN
在相同的表查询。
我能想到的替代方法是获取该用户标识的所有行,并在应用程序本身的for循环中处理它们,或尝试将名称限制为有限的数量并使用子SELECT
/ JOIN
。 然而,第二个选项是不理想的,如果添加一个新的名字,我不得不重新访问这个查询。
请告诉我,我错过了一些明显的东西
与其他一些RDBMS不同的是,MySQL并没有devise支持这种types的本地支持(开发人员认为它更适合于应用程序的表示,而不是数据库层)。
如果你绝对必须在MySQL中执行这样的操作,那么build立一个准备好的语句是一条可行的路线 – 尽pipe不是搞乱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
variables的限制(缺省值为1024字节:除非有一些非常长的name
值,否则不太可能相关)。