【问题标题】:Left outer join doesn't exclude when both the table have null values当两个表都有空值时,左外连接不排除
【发布时间】:2021-08-01 04:19:24
【问题描述】:

我有一个要求,我必须提取左表独有的数据。我为此使用左外连接。但是输出提取的数据对于两个表中连接条件中使用的变量都具有空值,这不是预期的。以下是详细情况,

表A

id name subject
1 tom math
2 jack null

表B

id name subject
3 john science
2 jack null

查询

SELECT * 
  FROM TableA 
  LEFT JOIN TableB 
    ON a.id = b.id
   AND a.subject = b.subject
 WHERE b.id IS NULL
   AND b.subject IS NULL

预期输出

id name subject
1 tom math

实际输出

id name subject
1 tom math
2 jack null

【问题讨论】:

  • LEFT JOIN 从不减少左表,因此您只需要 JOIN 以实现引用完整性或使用单独的WHERE a.subject is not null

标签: sql oracle join left-join rdbms


【解决方案1】:

问题在于,在您的问题要求中,您似乎需要将null 视为等于(其他)null

这违背了null 的定义。但是你可以达到你需要的结果——在加入条件下,改变

and a.subject = b.subject

and (a.subject = b.subject or (a.subject is null and b.subject is null))

在 Oracle 中,您可以更简洁地做到这一点:

and decode (a.subject, b.subject, 1) = 1

因为decode 被有意定义为将两个null 视为“相等”。

如果需要,您可以对 id 列执行相同操作 - 但假设它应该是两个表中的主键,则不需要它。

编辑 OP 声称decode 的建议使用会产生错误的结果,而or (a.subject is null and b.subject is null) 的显式使用会在SQL Developer 上无限期运行。因此,在此编辑中,我将表明 OP 的声明都是错误的。 (我在我的 SQL Developer 副本上运行了所有内容,所以 IDE 不是问题。)

他在做什么,我们不知道,但是对于所提供的数据和给我们的查询,这两个建议都是 100% 正确的(在我们添加了 OP 查询中缺少的表别名之后,我们仅选择来自TableA 的数据)。

测试数据:

create table tablea (id, name, subject) as
  select 1, 'tom' , 'math'    from dual union all
  select 2, 'jack', null      from dual
;

create table tableb (id, name, subject) as
  select 3, 'john', 'science' from dual union all
  select 2, 'jack', null      from dual
;

第一个查询和结果:

SELECT a.* 
  FROM TableA a
  LEFT JOIN TableB b 
    ON a.id = b.id
   AND (a.subject = b.subject or (a.subject is null and b.subject is null))
 WHERE b.id IS NULL
   AND b.subject IS NULL
;

        ID NAME SUBJECT
---------- ---- -------
         1 tom  math

第二次查询和结果:

SELECT a.* 
  FROM TableA a
  LEFT JOIN TableB b 
    ON a.id = b.id
   AND decode(a.subject, b.subject, 1) = 1
 WHERE b.id IS NULL
   AND b.subject IS NULL
;

        ID NAME SUBJECT
---------- ---- -------
         1 tom  math

【讨论】:

  • 我尝试了 decode 和 coalesce 但仍然,空行出现在输出中,并且 (a.subject = b.subject 或 (a.subject 为 null 并且 b.subject 为 null))查询在 Oracle SQL Developer 中无限期运行。
  • @VinayGowda - 那么你做错了什么。我将添加演示以证明我提出的建议在您提供的数据上非常有效。也许您的数据非常不同,或者您在查询中犯了错误(或两者兼而有之)。在任何情况下,您发布的查询都是错误的,因为您使用了未定义的别名 abfrom 子句中的表显示为 TableATableB,没有别名。 (select 也应该是 select a.* 而不是 select *,但这不是语法错误。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多