【问题标题】:I'm searching for a column that is empty how do I make it appear anyway我正在寻找一个空的列,无论如何我如何让它出现
【发布时间】:2022-01-18 01:30:05
【问题描述】:

我有一个任务要做,我必须通过搜索产品 ID 来获取所有详细信息(product_purchase、price_history、名称、类型、id 和价格的产品列)。 现在我有这个代码

SELECT * 
FROM price_history
LEFT JOIN product_purchase on price_history.product_id = product_purchase.product_id
INNER JOIN product ON price_history.product_id = product.id
WHERE product.id = 1

唯一的问题是如果产品从未被购买过(product.id 不在 product_purchase 表中,因为它从未被添加过)它不会显示任何其他列。尽管product_purchase 上不存在,但我该怎么做?我认为我的答案是正确的,但不知何故它不起作用。

【问题讨论】:

  • 看来你应该在 FROMLEFT JOINing 中从 product 开始。
  • 此 OP 提出的上一个问题也相关

标签: sql sql-server tsql


【解决方案1】:

您无法使用您选择的连接运算符按照您选择的方向通过您的表

 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 产品添加到那些“可能为空”的行将再次删除所有空值,因为没有任何东西等于空值,所以 NULLprice_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 内连接产品,您会做得更好,因为您将内连接到一个没有从在左连接期间谓词失败,但我想更多地谈谈让您考虑构建数据集的途径并了解数据库如何将数据粘在一起,而不仅仅是说“更改它,它会起作用”

【讨论】:

    猜你喜欢
    • 2015-02-03
    • 2022-06-29
    • 2020-03-21
    • 2017-09-19
    • 2011-05-06
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多