您无法使用您选择的连接运算符按照您选择的方向通过您的表
price_history LEFT JOIN product_purchase INNER JOIN product
将被评估为:
price_history LEFT JOIN product_purchase -> result
result INNER JOIN product
price_history left join purchase 将为任何尚未购买的产品引入 NULL。然后将 INNER JOIN 产品添加到那些“可能为空”的行将再次删除所有空值,因为没有任何东西等于空值,所以 NULL 在price_history.product_id 列不等于任何 product.product_id 值。这意味着未购买的产品将从结果中消失。
当您计划表路由并且不想丢失“可能为该列为空”的行时,您应该确保“可能为空”的表在右侧,当您这样做时左连接; LEFT 连接的 LEFT 侧是“实心”侧/始终包含所有记录的一侧
为此,您可能需要如下路线:
product
LEFT JOIN price_history ON product... = price_history...
LEFT JOIN product_purchase ON product... = product_purchase...
对于任何给定的产品,如果没有价格历史记录,那么左联接将原谅它并保留该产品。与产品购买相同;如果没有购买,则允许加入失败并保留产品行
还有其他方法可以避免您看到的问题,但通常使用的一个好的模式是“先进行所有内连接,然后再进行左连接”。如果一个产品绝对肯定会有至少一个 price_history,那么它可能是 INNER JOIN 而不是 left
脚注:不要在 WHERE 子句中提及您已离开加入的表。说类似WHERE product_purchase.product_id = 1 将撤消您在制作左联接时所做的所有工作,因为 nothig 永远等于 null 因此,所有由 LEFT JOIN 插入的行以确保即使没有匹配也保留该行,然后突然再次删除,因为您在 WHERE 子句中将 NULL 与 = 1 进行了比较(结果是false,因此该行从结果中消失)
如果您需要对左连接的表进行谓词,请考虑在 ON 而不是 WHERE 中执行此操作
最后,请注意:您要加入的两个表似乎很可能每个产品都有多行,这将导致笛卡尔爆炸。对于产品 X,如果有 2 行历史记录和 3 次购买,您将获得 6 行,除非您努力将历史记录和购买联系在一起,以使当时有效的价格(来自历史记录)是给予的价格根据购买日期进行购买
旁注,如果您在使用 price_history product_id 而不是 product_purchase product_id 内连接产品,您会做得更好,因为您将内连接到一个没有从在左连接期间谓词失败,但我想更多地谈谈让您考虑构建数据集的途径并了解数据库如何将数据粘在一起,而不仅仅是说“更改它,它会起作用”