【问题标题】:SQL. Left Join and Null value when column doesn't existsSQL。列不存在时的左连接和空值
【发布时间】:2017-02-12 21:31:26
【问题描述】:

我被困在一个查询中。希望有人可以在这里帮助我。

我有这 4 张桌子:

表格:项目

id_items
1

表:items_atr_currencies_match

id_items_atr_currencies_match | id_items_atr_currencies | id_items
1                             | 1                       | 1

表格:items_atr_currencies_translations

id_items_atr_currencies_translations | id_items_atr_currencies | id_language_code | translation
1                                    | 1                       | 1                | $

表:items_atr_currencies

id_items_atr_currencies
1   

表格:语言

id_languages | language_code
1            | es
2            | en

我的查询:

SELECT
    id_items,
    iact3.translation AS currency

FROM
    items i

LEFT JOIN 
    items_atr_currencies_match AS iacm3 ON iacm3.id_items = i.id_items
LEFT JOIN 
    items_atr_currencies AS iac3 ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies
LEFT JOIN 
    items_atr_currencies_translations AS iact3 ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies 
LEFT JOIN 
    languages AS l ON l.id_languages = iact3.id_language_code OR iact3.id_language_code IS NULL

WHERE
    i.id_items = 1
    AND l.language_code = "en" 

预期结果:

id_items | currency
1        | null

得到 0 结果而不是

我想我在最后一个 LEFT JOIN 中遗漏了类似“OR iact3.id_language_code 不存在”的内容,但我不知道该怎么做。

当表 items_atr_currencies_match 没有数据或表 items_atr_currencies_translations 有翻译但有数据且翻译不存在时,它可以正常工作。

提前谢谢你

* 更新 *

最后这个查询正在做我想做的事:

SELECT 
     i.id_items,            
     iact3.translation AS currency

FROM
     items i

LEFT JOIN 
     languages AS l ON l.language_code = 'en'
LEFT JOIN 
     items_atr_currencies_match AS iacm3 ON iacm3.id_items = i.id_items
LEFT JOIN 
     items_atr_currencies_translations AS iact3 ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies 
     AND l.id_languages = iact3.id_language_code            
LEFT JOIN items_atr_currencies AS iac3 ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies

WHERE
    i.id_items = 1

我所要做的就是将语言 LEFT JOIN 移动到第一个位置并检查那里的语言代码。

【问题讨论】:

  • 您可能需要将最后一个条件移动到连接中:LEFT JOIN languages AS l ON l.id_languages = iact3.id_language_code AND l.language_code = "en" WHERE i.id_items = 1。外连接的基本规则:外表的条件通常是 WHERE 的一部分,内表的条件添加到ON
  • 嗨@dnoeth,我得到结果“1 | $”但“en”翻译没有退出。不应该得到 1 |改为空?这就是我所期待的结果。谢谢

标签: mysql sql database join left-join


【解决方案1】:

您需要将条件AND l.language_code = "en" 移动到左连接中。否则,将在评估所有左连接后检查此条件,如果结果元组没有language_code = "en",它将从整体结果中消除。

如果您现在希望 currencies_translations 仅在它们映射到有效语言时才被考虑,那么您必须在“左连接”之前通过连接连接 currencies_translationslanguages 以及总体结果:

...
LEFT JOIN (select iact3.id_items_atr_currencies as iact3id from
    items_atr_currencies_translations AS iact3 JOIN 
    languages AS l ON (l.id_languages = iact3.id_language_code AND l.language_code = "en") OR iact3.id_language_code IS NULL) as iact3l 
    ON iact3l.iact3id = iacm3.id_items_atr_currencies 

【讨论】:

  • 感谢@stepahnLechner 的回答,现在我得到了结果,但没有得到正确的结果。我得到:` id_items |货币` ` 1 | $` 并且由于该翻译不存在,我期待:` id_items |货币` ` 1 | null`,有什么建议吗?谢谢
  • 我想您必须将currencies_translationslanguages 视为“关节中间结果”,然后可以通过整体查询将其视为左关节。请参阅编辑后的答案。希望它可以直接工作或稍作语法修改......
  • ... “$” 在结果中,因为实际上存在一个 items_atr_currencies_translations-entry,它没有被过滤掉,因为它与 language 的(不存在)连接只是“左连接”...
  • 嗨@Stephan,您的回答仍然给我相同的结果,但是我找到了解决方案。我将更新我的答案并接受您的权利,以感谢您的信息和帮助。谢谢
【解决方案2】:

您有一系列left joins。当您在第一个表之外的任何表的where 子句中有条件时,它往往会将left join 变成inner join。您需要将该条件放在on 子句中:

SELECT id_items,iact3.translation AS currency
FROM items i LEFT JOIN 
     items_atr_currencies_match AS iacm3
     ON iacm3.id_items = i.id_items LEFT JOIN 
     items_atr_currencies AS iac3 
     ON iac3.id_items_atr_currencies = iacm3.id_items_atr_currencies LEFT JOIN 
     items_atr_currencies_translations AS iact3
     ON iact3.id_items_atr_currencies = iacm3.id_items_atr_currencies  LEFT JOIN 
     languages AS l
     ON (l.id_languages = iact3.id_language_code OR iact3.id_language_code IS NULL) AND
        l.language_code = 'en' 
WHERE i.id_items = 1;

第一个表的条件放在WHERE 子句中。

注意:我认为最后一个条件可以简化为:

     ON l.id_languages = iact3.id_language_code AND
        l.language_code = 'en' 

即使没有匹配,LEFT JOIN 也会包含该行。

【讨论】:

  • 感谢您的回答,现在我得到了结果,但我没有得到正确的结果。我得到:` id_items |货币` ` 1 | $` 并且由于该翻译不存在,我期待:` id_items |货币` ` 1 | null` 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-22
  • 2021-02-01
相关资源
最近更新 更多