【问题标题】:Convert INNER JOIN to LEFT JOIN - Sql将 INNER JOIN 转换为 LEFT JOIN - Sql
【发布时间】:2017-05-31 09:10:18
【问题描述】:

我有一个返回 ~ 97k 记录的查询,因为我使用的是内连接。现在我想使用左连接来显示右表上的空记录(应该是大约 300k 记录)。这是实际的查询(INNER JOIN):

 select artnr as "Article number", ardbez1 as "Article description ", arpadrnr as "Supplier code", cd.ADPPHYSLAND as "Country of this supplier code", p.adrnr as "Parent supplier code", p.adrkname as "Name of parent", pd.ADPPHYSLAND as "Country of parent ", arppreis as "Price", arpwae as "Unit", arzwert as "COO", atatarnr as "HS Code"
    from mic_ccs_artikel, mic_ccs_artikeldetail, mic_ccs_artikelpreis, mic_dna_adressen c, mic_dna_adrdetail cd, mic_dna_adressen p, mic_dna_adrrelation, mic_dna_adrdetail pd, mic_ccs_artikelzoll, mic_ccs_artikeltarif
    where artsid = ardartsid
    and arddatstart <= sysdate
    and nvl(arddatend, '01.01.4000') >= sysdate
    and artsid = arpartsid
    and ARPPREISART = 'VP'
    and arpdatstart <= sysdate
    and nvl(arpdatend, '01.01.4000') >= sysdate
    and c.adrsid = cd.adpadrsid
    and arpadrnr = c.adrnr
    and cd.adpdatvon <= sysdate
    and nvl(cd.adpdatbis, '01.01.4000') >= sysdate
    and c.adrmandant = 'S1'
    and c.adrwerk = 'V1'
    and p.adrmandant = 'S1'
    and p.adrwerk = 'V1'
    and p.adrsid = arlrelsid1
    and c.adrsid = arlrelsid2
    and p.adrsid = pd.adpadrsid
    and pd.adpdatvon <= sysdate
    and nvl(pd.adpdatbis, '01.01.4000') >= sysdate
    and artsid = arzartsid
    and arztyp = 'URLD'
    and arzadrnr = c.adrnr
    and arzdatstart <= sysdate
    and nvl(arzdatend, '01.01.4000') >= sysdate
    and artsid = ataartsid
    and ATAREGION = 'SE' 
    and atatarart='EXPORT'
    and atadatstart <= sysdate
    and nvl(atadatend, '01.01.4000') >= sysdate
    ; 

然后我尝试将其“转换”为 LEFT JOIN,但它始终显示相同的结果:

select artnr as "Article number", ardbez1 as "Article description ", arpadrnr as "Supplier code", cd.ADPPHYSLAND as "Country of this supplier code", p.adrnr as "Parent supplier code", p.adrkname as "Name of parent", pd.ADPPHYSLAND as "Country of parent ", arppreis as "Price", arpwae as "Unit", arzwert as "COO", atatarnr as "HS Code"
from mic_ccs_artikel, mic_ccs_artikeldetail, mic_ccs_artikelpreis, mic_dna_adressen c, mic_dna_adrdetail cd, mic_dna_adressen p, mic_dna_adrrelation, mic_dna_adrdetail pd, mic_ccs_artikelzoll, mic_ccs_artikeltarif
where artsid = ardartsid(+)
and arddatstart <= sysdate
and nvl(arddatend, '01.01.4000') >= sysdate
and artsid = arpartsid(+)
and ARPPREISART = 'VP'
and arpdatstart <= sysdate
and nvl(arpdatend, '01.01.4000') >= sysdate
and c.adrsid = cd.adpadrsid(+)
and arpadrnr = c.adrnr
and cd.adpdatvon <= sysdate
and nvl(cd.adpdatbis, '01.01.4000') >= sysdate
and c.adrmandant = 'S1'
and c.adrwerk = 'V1'
and p.adrmandant = 'S1'
and p.adrwerk = 'V1'
and p.adrsid = arlrelsid1(+)
and c.adrsid = arlrelsid2
and p.adrsid = pd.adpadrsid
and pd.adpdatvon <= sysdate
and nvl(pd.adpdatbis, '01.01.4000') >= sysdate
and artsid = arzartsid(+)
and arztyp = 'URLD'
and arzadrnr = c.adrnr
and arzdatstart <= sysdate
and nvl(arzdatend, '01.01.4000') >= sysdate
and artsid = ataartsid(+)
and ATAREGION = 'SE' 
and atatarart='EXPORT'
and atadatstart <= sysdate
and nvl(atadatend, '01.01.4000') >= sysdate
;

为什么总是显示相同的结果?

【问题讨论】:

  • 使用别名,我们无法理解哪些列属于哪个表
  • 我建议你使用左外连接语法
  • 您应该限定每个属性,使用别名并开始使用 ANSI 连接语法 (join...on...)。您的直接问题可能是您的左连接表在您的where 中也有一个条件,有效地将其变成了内连接。
  • 使用 ANSI 连接语法 - 您会发现更容易发现错误,您问题的读者也将如此!
  • 如 HoneyBadger 所述。使用所有 alias.column 引用获取您的查询。完成后,我们可以更好地帮助您清理查询语法。

标签: sql oracle left-join


【解决方案1】:

呼应 cmets 中的情绪,使用左连接和 where 子句可能会导致一些意外行为。请参阅我的回答here,了解更多关于为什么会发生这种情况的详细信息。基本上,您应该切换到使用 ANSI 语法并为您的表设置别名。在你的情况下,这看起来像

select * -- select whichever fields you want here
    from mic_ccs_artikel a -- only one table in the from clause
    left join mic_ccs_artikeldetail b on b.someID = a.someID -- join conditions here
    left join mic_ccs_artikelpreis c
        on c.someID = a.someID -- join conidition
        and c.someField = 'Some Property' -- filtering here
    ...

辅助连接条件消除了在 where 子句中丢弃这些记录的风险。同样,请参阅 my other answer 了解更多详情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 2015-01-10
    • 2016-10-31
    • 2023-03-17
    • 2015-03-03
    • 2018-07-10
    • 1970-01-01
    相关资源
    最近更新 更多