如何在MySQL中执行多个LEFT JOIN?

时间:2012-12-14 18:33:28

标签: mysql select left-join

首先让我描述一些背景。我们有一个包含所有产品的表格,以及一个包含“产品标签”列表(材料/尺寸/类型)的表格,以及一个包含分配给产品的标签列表的表格('tag_id'= > 1(材料),'价值'=>'黄金','产品'=> 123)

我正在尝试使用与此类似的查询来过滤掉某些产品,但它似乎不起作用。任何人都可以在正确的方向上提供一些指示吗?

SELECT DISTINCT `products`.* FROM `products`,`product_assigned_tags`
LEFT JOIN `product_assigned_tags`   AS tags_0 ON tags_0.`tag_id` = 1
LEFT JOIN `product_assigned_tags`   AS tags_1 ON tags_1.`tag_id` = 2
WHERE (
    ((tags_0.`value` = 'silver' ) AND (tags_0.`value` != 'gold' ) ) AND
    ((tags_1.`value` = 'small' ) AND (tags_1.`value` != 'large' ) )
) AND (`products`.`type` = '2' OR `products`.`type` = '1' ) LIMIT 0, 30

1 个答案:

答案 0 :(得分:1)

您的查询存在一些问题。

首先,您有一个CROSS JOIN,它将生成一个笛卡尔积,从products返回的每一行都将与product_assigned_tags中的每一行匹配。

此外,由于WHERE子句中的谓词,您的下两个连接实际上根本不是LEFT连接(它们不是外连接)。检查value = 'foo'实际上是否定了外连接。

另外,你的一些谓词是多余的。

如果value = 'silver'的计算结果为true,那么value != 'gold'保证为真,则不需要包含该不等式谓词。


product_assigned_tags表似乎与产品相关,product_id列作为products.id的外键。 (没有任何架构定义,我只是在猜测。

SELECT DISTINCT p.*
  FROM `products` p
  JOIN `product_assigned_tags` tags_0
    ON tags_0.product_id = p.id
   AND tags_0.`tag_id` = 1
   AND tags_0.`value` = 'silver'
  JOIN `product_assigned_tags` tags_1 
    ON tags_1.product_id = p.id 
   AND tags_1.`tag_id` = 2
   AND tags_1.`value` = 'small'
 WHERE p.`type` IN ('1','2')
 ORDER BY 1
 LIMIT 0,30

问:我如何处理JOIN的'OR'案例?例如:客户选择查看材料为“gold”或“silver”的所有产品?

A:表达联接谓词中的OR条件,例如

   AND tags_0.`value` IN ('silver','gold')

相当于:

   AND ( tags_0.`value` = 'silver' OR tags_0.`value` = 'gold')