MySQL查询 - 根据两个因素加入数据,然后根据值自定义数据的排序方式

时间:2010-06-22 14:26:10

标签: sql mysql

首先,我是新来查询多个表,所以我很抱歉这是一个有点愚蠢的问题,但我们都必须从某个地方开始!

我制作了一张图片,让人们更容易理解:

http://www.mediumsliced.co.uk/temp/mysqlhelp.jpg

我的第一个表 wp_user 有几列 - 我希望3列中的值为ID user_email和user_nicename。
我的第二个表 wp_usermeta 有3列,用于存储用户的元数据。这些列是user_id,meta_key和meta_value。此表中的user_id值始终对应于 wp_user 中的匹配ID值(参见图片)。

我想加入meta_key字段中的数据及其meta_value。到目前为止,我有这个:

SELECT wp_users.ID, wp_users.user_login, wp_users.user_nicename, wp_users.user_email,
       wp_usermeta.user_id, wp_usermeta.meta_key, wp_usermeta.meta_value
FROM wp_users, wp_usermeta
WHERE (wp_users.ID = wp_usermeta.user_id);

这显示了我需要的所有信息,但是我遇到的问题是我实际上想要将meta_key中的数据显示为单个列,并根据其ID在该用户的正确行中显示该元键的meta_value。我还需要排除任何没有wp_user_level为0的用户。(再次希望我提供的图片更加清晰)

显然我需要学习很多关于MySql的内容,但是如果有人能指导我到最终结果我真的很感激,如果你能解释一下这个查询以便我可以从中学习而不是只需将其复制并粘贴到位。

如果您需要更多信息或需要我澄清任何内容,请随时提出申请,我们非常感谢!

克雷格

4 个答案:

答案 0 :(得分:3)

Select wp_users.ID
    , wp_users.user_login
    , wp_users.user_email
    , wp_users.user_nicename
    , Min( Case When wp_usermeta.meta_key = 'first_name' Then wp_usermeta.meta_value End ) As first_name
    , Min( Case When wp_usermeta.meta_key = 'last_name' Then wp_usermeta.meta_value End ) As last_name
    , Min( Case When wp_usermeta.meta_key = 'address' Then wp_usermeta.meta_value End ) As address
    , Min( Case When wp_usermeta.meta_key = 'dob' Then wp_usermeta.meta_value End ) As dob
From wp_user
    Join wp_usermeta
        On wp_usermeta.user_id = wp_user.ID
Where Exists    (
                Select 1
                From wp_usermeta As Meta1
                Where Meta1.user_id = wp_user.id
                    And Meta1.meta_key = 'wp_user_level' 
                    And Meta1.meta_value = '0' 
                )
        And wp_usermeta.meta_key In('first_name','last_name','address','dob')                   
Group By wp_users.ID
    , wp_users.user_login
    , wp_users.user_email
    , wp_users.user_nicename

首先,正如其他人所提到的,这个查询编写起来很麻烦的原因之一是你必须使用EAV结构。 “元”表的概念实际上是关系设计的一种诅咒。其次,为了从EAV中获取信息,您必须创建所谓的交叉表查询,您可以在其中构建查询中所需的列。通常,关系数据库不是为动态列生成而设计的,例如我在我的解决方案中进行并且是EAV所必需的。

答案 1 :(得分:2)

继续你的例子

SELECT 
    wp_users.ID, 
    wp_users.user_login, 
    wp_users.user_nicename, 
    wp_users.user_email, 
    wp_usermeta.user_id, 
    wp_usermeta.meta_key, 
    wp_usermeta.meta_value 
FROM 
    wp_users, wp_usermeta 
WHERE 
   (wp_users.ID = wp_usermeta.user_id) AND (wp_usermeta.wp_user_level = 0);

应该给你你需要的东西。 注意:

  • 格式化您的SQL
  • 而不是id = user_id上的WHERE条件,它可能是一个连接
像这样:

SELECT 
    ...
FROM 
    wp_users INNER JOIN
    wp_usermeta ON wp_users.id = wp_usermeta.user_id
WHERE
    wp_usermeta.wp_user_level = 0

编辑:至于元数据和元属性,您必须多次加入meta_table,因为会有属性

所以例如得到

SELECT 
    wp_users.ID, 
    wp_users.user_login, 
    wp_users.user_nicename, 
    wp_users.user_email, 
    m1.meta_value as first_name
    m2.meta_value as last_name
    m3.meta_value as address
    m4.meta_value as dob
FROM 
    wp_users 
    INNER JOIN wp_usermeta m ON wp_users.id = m.user_id AND m.meta_key = "wp_user_level" AND m.meta_value = 0
    LEFT JOIN wp_usermeta m1 ON wp_users.id = m1.user_id AND m1.meta_key = "first_name"
    LEFT JOIN wp_usermeta m2 ON wp_users.id = m2.user_id AND m1.meta_key = "last_name"
    LEFT JOIN wp_usermeta m3 ON wp_users.id = m3.user_id AND m1.meta_key = "address"
    LEFT JOIN wp_usermeta m4 ON wp_users.id = m4.user_id AND m1.meta_key = "dob"       

正如您可以看到EAV方法,虽然它允许重复使用UI元素,但不会对数据库的实际结构产生奇迹(更慢更复杂的查询,有限的完整性验证以及最终代码在这种结构上运作的更复杂。)

如果可能,正确的方法是在应用程序级别处理“聚合”。

答案 2 :(得分:1)

假设wp_usermeta中存在所有密钥,您可以简单地多次加入该表。如果可能缺少值,请使用Left Join

Select
  u.ID,
  u.user_login,
  u.user_nicename,
  u.user_email,
  m_first_name.meta_value As first_name,
  m_last_name.meta_value  As last_name,
  m_address.meta_value    As address,
  m_dob.meta_value        As dob
From wp_users u
Join wp_usermeta m_first_name On (     m_first_name.user_id = u.id
                                   And m_first_name.meta_key  = 'first_name' )
Join wp_usermeta m_last_name  On (     m_last_name.user_id    = u.id
                                   And m_last_name.meta_key   = 'last_name' )
Join wp_usermeta m_address    On (     m_address.user_id      = u.id
                                   And m_address.meta_key     = 'address' )
Join wp_usermeta m_dob        On (     m_dob.user_id          = u.id
                                   And m_dob.meta_key         = 'dob' )
Join wp_usermeta m_user_level On (     m_user_level.user_id   = u.id
                                   And m_user_level .meta_key = 'm_user_level' )
Where m_user_level.meta_value = '0';

答案 3 :(得分:0)

对于要从中提取的每个值,你必须分别将meta连接到元表。这就是为什么EAV表是关系数据库的反模式的原因之一。

另外请学习明确加入。隐式连接会让你遇到麻烦,因为当事情变得复杂时它们会导致偶然的交叉连接(并且你只会用设计这么糟糕的情况编写复杂的查询。)当你需要离开连接时它们也很糟糕(因为你会因为你不知道这个糟糕的设计需要做什么;不知道这个人是否对每个attriubute都有一个线索。