【问题标题】:LEFT JOIN null values conceptLEFT JOIN 空值概念
【发布时间】:2020-10-11 10:33:34
【问题描述】:

我有“products”和“product_translations”表。 “product_translations”表有: id、product_id、locale、name 字段。

现在我想选择这样的产品和翻译:

SELECT * FROM products AS P
LEFT JOIN product_trs Ptr on P.id = Ptr.product_id
WHERE locale = 'fr'

但问题是,如果产品没有翻译(但)这些产品不会被退回。

例如,假设我的 product_translations 包含这些行:

id  pr_id locale    name
------------------------------
1    1    'en'    'product 1'
2    1    'fr'    'produit 1'
3    2    'en'    'product 2'

现在如果我选择

WHERE locale = 'en'

如果我运行查询,我将得到 2 行:

WHERE locale = 'fr'

我会得到一排

我想总是得到 2 行。即使我没有翻译。我该怎么做?

【问题讨论】:

  • 不完整 -- locale 在哪个表中?
  • @RickJames in product_trs(产品翻译)
  • 那么,真的不是LEFT加入吗?
  • @RickJames,为什么?
  • LEFT 暗示“右”表中可能有一行。 WHERE locale = 'fr' 表示必须有一行(并且应该具有该值)。我(例如)需要分析查询。 (绝不是你唯一一个虚假地使用LEFT 的人。)戈登的回答正确地使用了LEFT。这是ONWHERE 行为不同的简单示例。 (在许多情况下,你在哪个地方设置条件并不重要。)

标签: mysql sql database-design


【解决方案1】:

您需要将where 子句中的条件移动到on 子句中:

SELECT *
FROM products P LEFT JOIN
     product_trs Ptr 
     ON P.id = Ptr.product_id AND ptr.locale = 'fr';

否则,过滤发生在left join 之后——locale 然后是NULL,比较失败。

一般规则是left join 中第一个表的过滤器进入where 子句。第二个(及后续)表的过滤器位于 on 子句中。

【讨论】:

    【解决方案2】:

    当您在“where”中编写过滤器时,记录会从结果中删除,但如果您将其置于“连接条件”中,则记录只是从表中过滤而不是从结果中过滤并返回 null。 所以戈登的答案是正确的。

    SELECT *
    FROM products P LEFT JOIN
     product_trs Ptr 
     ON P.id = Ptr.product_id AND ptr.locale = 'fr';
    

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多