在MySQL中使用NULL值连接相同的表

时间:2014-06-16 13:25:12

标签: mysql sql

我有一个像

这样的简单表格
user_id | meta_key | meta_value
===============================
   1    | color    | green
   2    | color    | red
   1    | size     | L
   2    | size     | L
   3    | color    | blue

...

现在我喜欢单个查询,我可以获得某个用户的所有颜色和大小

SELECT a.user_id AS ID, a.meta_value AS color, b.meta_value AS size
   FROM table AS a
   LEFT JOIN table AS b ON a.user_id = b.user_id 
WHERE a.meta_key = 'color' AND b.meta_key = 'size' GROUP BY a.meta_value, b.meta_value

只要每个用户都有一个size,这就行了。如果缺少size(示例中为ID 3),则用户不在结果中

4 个答案:

答案 0 :(得分:2)

b.meta_key 中的WHERE上的谓词否定了LEFT JOIN操作的“外部性”。

一种选择是将该谓词重新定位到 ON 子句,例如:

SELECT a.user_id AS ID, a.meta_value AS color, b.meta_value AS size
   FROM table AS a
   LEFT JOIN table AS b ON a.user_id = b.user_id 
      AND b.meta_key = 'size'
 WHERE a.meta_key = 'color' GROUP BY a.meta_value, b.meta_value

<强>后续

问:如果缺少color怎么办?

A:您需要一个表或内联视图作为行源,返回您希望包含在结果集中的每个user_id值。例如,如果您有一个名为“users”的表,每个user_id有一行,并且您希望返回该表中的每个id

 SELECT u.id         AS user_id
      , a.meta_value AS color
      , b.meta_value AS size
   FROM user u
   LEFT
   JOIN `table` a
     ON a.user_id = u.id
    AND a.meta_key = 'color'
   LEFT
   JOIN `table` b
     ON b.user_id = u.id
    AND b.meta_key = 'size'
  GROUP
     BY u.id
      , a.meta_value
      , b.meta_value

我们还注意到原始查询中的GROUP BY不包含user_id列,因此任何颜色和大小相同meta_value的行都会折叠,而您只会获得一个具有匹配颜色和大小的user_id值。

请注意,如果user_idmeta_key的组合为UNIQUE(在表table中),则不需要GROUP BY。


在规范关系模型中,实体的属性实现为列。作为一个很好的例子,查询返回的结果集看起来很像我们期望的表。

当在关系数据库中实现实体属性值(EAV)模型时,SQL会变得更复杂。


如果您只想返回具有colorsize的user_id的值,您可以获得带有内联视图的user_id值列表(针对table的查询)。此查询与上述相同,但使用内联视图替换对user表的引用:

 SELECT u.id         AS user_id
      , a.meta_value AS color
      , b.meta_value AS size
   FROM ( SELECT t.user_id AS id
            FROM table t
           WHERE t.meta_key IN ('color','size')
          GROUP BY t.user_id
        ) u
   LEFT
   JOIN `table` a
     ON a.user_id = u.id
    AND a.meta_key = 'color'
   LEFT
   JOIN `table` b
     ON b.user_id = u.id
    AND b.meta_key = 'size'
  GROUP
     BY u.id
      , a.meta_value
      , b.meta_value

答案 1 :(得分:1)

where子句会杀了你。我们来看b.meta_key = 'size'。如果B表中没有行,则meta_key将返回null。该列上的过滤器将其从结果中删除。尝试将b.meta_key = 'size'添加到on子句中。

答案 2 :(得分:0)

尝试以下代码,

SELECT a.user_id AS ID, a.meta_value AS color, b.meta_value AS size FROM table AS a where a.meta_key = 'color' or a.meta_key = 'size'

答案 3 :(得分:0)

SELECT a.user_id AS ID,
a.meta_value AS color, b.meta_value AS size
FROM table AS a
LEFT JOIN table AS b ON a.user_id = b.user_id 
WHERE a.meta_key in ('Color', 'Size')