如何根据连接的表值选择“假”列/值?

时间:2013-08-06 20:10:54

标签: mysql wordpress select inner-join

简短版本:

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

长版:

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

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

meta_idpost_idmeta_keymeta_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中,所选答案使用硬编码字段。我想自动这样做。 :)

2 个答案:

答案 0 :(得分:2)

它被称为Entity–attribute–value model。通过简单/复杂查询在MySQL中动态列(元数据)的解决方案是AFAIK无法实现的(像其他很棒的函数,如PIVOT MySQL缺失)。我认为唯一的方法是静态定义或MySQL function,它从元表中获取可能的属性并构建正确的查询。

请查看What is best performance for Retrieving MySQL EAV results as Relational Table

还可以在堆栈Entity-Attribute-Value Table Design

上阅读有关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