4

简洁版本:

我需要自定义查询结果,使用一个值作为列名,另一个值作为列的值。它还需要是自动的(不是硬编码,数百个可能的“元键”)。

长版:

我正在使用 Wordpress 的“用户元”结构,其中单个用户有一个用户 ID,另一个表包含与用户相关的“元数据”。

这个元数据是任意的,只有四列:

meta_id, post_id, meta_key, meta_value.

我想对某个用户进行 SQL 查询,并对结果进行格式化,以便所有元数据都像行一样被格式化,其中meta_key是列名,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

期望的结果:

* user_id | username | email             | first-name | last-name | newsletter
35        | radgh    | radgh@example.org | Radley     | Sustaire  | on

在这个类似的问题中,所选答案使用硬编码字段。我想自动执行此操作。:)

4

2 回答 2

2

它被称为实体-属性-价值模型。通过简单/复杂查询在 MySQL 中动态列(元数据)的解决方案是 AFAIK 无法实现的(就像PIVOT缺少其他伟大的功能,如 MySQL 一样)。我认为唯一的方法是静态定义或MySQL 函数,它从元表中获取可能的属性并构建正确的查询。

请查看以关系表形式检索 MySQL EAV 结果的最佳性能是什么

另请阅读有关堆栈实体-属性-值表设计的EAV 设计(优点/缺点)

于 2013-08-06T20:26:54.093 回答
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;

在此处查看小提琴。

于 2013-08-06T20:37:30.793 回答