简短版本:
我需要自定义查询结果,使用一个值作为列名,另一个值作为列的值。它还需要是自动的(不是硬编码,数百种可能的“元键”)。
长版:
我正在使用Wordpress的“用户元”结构,其中单个用户具有用户ID,另一个表包含与用户相关的“元数据”。
此元数据是任意的,只有四列:
meta_id
,post_id
,meta_key
,meta_value
。
我想为某个用户执行SQL查询,并格式化结果,以便将所有元数据格式化为行,meta_key
是列名,{{1是列的值。
示例数据库:
meta_value
我的查询(我需要找出(???)部分,这会生成元键/值对作为假列)
-- wp_users
* ID | username | email
35 | radgh | radgh@example.org
-- wp_usermeta
* meta_id | user_id | meta_key | meta_value
1 | 35 | first-name | Radley
2 | 35 | last-name | Sustaire
3 | 35 | newsletter | on
期望的结果:
SELECT
`users`.ID as 'user_id',
`users`.username as 'username',
`users`.email as 'email',
(???)
FROM `wp_users` `users`
INNER JOIN `wp_usermeta` `meta`
ON `users`.ID = `meta`.user_id
WHERE `wp_users`.ID = 35
在此similar question中,所选答案使用硬编码字段。我想自动这样做。 :)
答案 0 :(得分:2)
它被称为Entity–attribute–value model。通过简单/复杂查询在MySQL中动态列(元数据)的解决方案是AFAIK无法实现的(像其他很棒的函数,如PIVOT
MySQL缺失)。我认为唯一的方法是静态定义或MySQL function,它从元表中获取可能的属性并构建正确的查询。
请查看What is best performance for Retrieving MySQL EAV results as Relational Table
上阅读有关EAV设计(优缺点)的内容答案 1 :(得分:2)
MySQL没有透视功能。如果您已经知道meta_key的所有可能值,则可以使用如下的硬编码查询:
SELECT
wp_users.*,
MAX(CASE WHEN `meta_key`='first-name' THEN meta_value END) AS `first-name`,
MAX(CASE WHEN `meta_key`='last-name' THEN meta_value END) AS `last-name`,
....
FROM
wp_users INNER JOIN wp_usermeta
ON wp_users.ID=wp_usermeta.user_id
GROUP BY
wp_users.ID, wp_users.username, wp_users.email;
或者您可以使用预准备语句动态创建SQL查询,如下所示:
SELECT
CONCAT(
'SELECT wp_users.*,',
GROUP_CONCAT(
CONCAT(
'MAX(CASE WHEN `meta_key`=\'',
meta_key,
'\' THEN meta_value END) AS `',
meta_key,
'`')),
' FROM wp_users INNER JOIN wp_usermeta ON wp_users.ID=wp_usermeta.user_id',
' GROUP BY wp_users.ID, wp_users.username, wp_users.email')
FROM
(SELECT DISTINCT meta_key FROM wp_usermeta) s
INTO @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
请参阅小提琴here。