【问题标题】:How to perform multiple LEFT JOIN's in MySQL?如何在 MySQL 中执行多个 LEFT JOIN?
【发布时间】:2012-12-14 18:33:27
【问题描述】:

让我先描述一些背景。我们有一个包含我们所有产品的表,一个包含“产品标签”列表(材料/尺寸/类型)的表,以及一个包含分配给产品的标签列表的表(“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 @MichaelBerkowski
  • @Michael:实际上,OP 查询中没有任何真正的 LEFT 连接。 WHERE 子句中的谓词否定“左连接”的任何“外部”特性,使它们等同于“内连接”。而第一个连接实际上是一个交叉连接。

标签: mysql select left-join


【解决方案1】:

您的查询中有一些问题。

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

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

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

如果value = 'silver' 的计算结果为真,则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 的“或”情况?例如:客户选择查看材质为“金”或“银”的所有产品?

A: 在连接谓词中表达OR 条件,例如

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

相当于:

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

【讨论】:

  • 这似乎是合乎逻辑的方式。但是,我将如何处理带有 JOIN 的“OR”案例?例如:客户选择查看材质为“gold”或“silver”的所有产品?
  • @R4wizard:我会在 JOIN 谓词中表达 OR 条件。 tags_0.value = 'gold' 或 tags_0.value = 'silver'。由于 AND 和 OR 之间的优先顺序,请务必将 OR 表达式括在括号中。上面更新了答案。
猜你喜欢
  • 1970-01-01
  • 2023-01-09
  • 2013-05-14
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 2018-12-15
  • 2011-06-24
相关资源
最近更新 更多