【问题标题】:LEFT JOIN drops rows without filtering original tableLEFT JOIN 删除行而不过滤原始表
【发布时间】:2016-09-14 23:05:21
【问题描述】:

以下查询让我感到困惑。如果我执行WHERE (inventory_to_pos.POSID IS NULL OR inventory_to_pos.POSID = ?) 并绑定POSID,它可能显示products 表中的所有行,而inventory_to_pos 中可能存在也可能不存在。当LEFT JOIN-ing 表时,我是否应该从原始表中获取 all 行,当我只过滤原始表并在 LEFT JOIN'ed 表的任何条件下使用 IS NULL 时?

SELECT products.ID,products.NAME,products.VOLUME,productcombinations.PRODUCTID,productcombinations.PART,inventory_to_pos.FULLCOUNT
FROM products
LEFT JOIN productcombinations ON products.ID = productcombinations.PARTOF
LEFT JOIN inventory_to_pos ON products.ID = inventory_to_pos.PRODUCT 
WHERE products.INVENTORY = 1
AND products.AVAILABLE = 1
AND products.ID > 0
AND (inventory_to_pos.POSID IS NULL OR inventory_to_pos.POSID = ?);

如果给定的产品和 POSID 不存在 inventory_to_pos.PRODUCTinventory_to_pos.POSID,则我不会得到任何行。为什么?

【问题讨论】:

  • LEFT JOIN + WHERE = INNER JOIN(在同一张表上),所以将这些附加条件放入 LEFT JOIN 语句中。
  • 如何相等?我没有在左连接的列上使用 WHERE?你能举例说明你的意思吗?
  • 你在尝试WHERE inventory_to_pos.POSID IS NULL,对吧?
  • 是的,但是 OR 有值 X(绑定)?我看不出有什么不同。
  • 请发布一个带有修复的答案,以便我理解。

标签: mysql left-join


【解决方案1】:

将所有相关的invetory_to_pos 子句移入LEFT JOIN,即:

SELECT
    products.ID,
    products. NAME,
    products.VOLUME,
    productcombinations.PRODUCTID,
    productcombinations.PART,
    inventory_to_pos.FULLCOUNT
FROM
    products
LEFT JOIN productcombinations ON products.ID = productcombinations.PARTOF
LEFT JOIN inventory_to_pos ON products.ID = inventory_to_pos.PRODUCT AND (
    inventory_to_pos.POSID IS NULL
    OR inventory_to_pos.POSID = ?
)
WHERE
    products.INVENTORY = 1
AND products.AVAILABLE = 1
AND products.ID > 0

【讨论】:

  • 成功了。哇。这是我对如何过滤联接的一般知识的巨大差距。
  • 您能否向我解释一下为什么我们不能在 WHERE 中过滤?我一直认为这是所有过滤器都应该去的地方。
  • 一般来说,因为 MySQL 首先过滤表本身(它需要所有 WHERE 语句)然后进行连接。因此,在您的情况下,引擎首先将根据您的 WHERE 子句过滤inventory_to_pos,然后将其加入,这等于 INNER JOIN。
  • 但是....根据我的 WHERE 子句,我想要为 NULL 或具有特定值的行。我无法理解这等于 INNER JOIN,它需要两个表中的行?完全被难住了。
  • 如果你在 LEFT JOIN 中使用WHERE inventory_to_pos.POSID IS NULL insead,引擎将只从products 表中获取与此条件匹配的相应记录以及products.ID = inventory_to_pos.PRODUCT。使用 LEFT JOIN,引擎首先获取所有 products 行,然后加入第二个表并将他的行“粘合”到原始表。希望您能理解这些解释的不同之处:)
猜你喜欢
  • 2017-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2021-09-27
  • 2017-10-31
相关资源
最近更新 更多