【问题标题】:Oracle SQL Full Outer JoinsOracle SQL 全外连接
【发布时间】:2018-05-01 17:05:59
【问题描述】:

我的表格如下:

SELECT * FROM r_a;

CLASS   SECTION
-----   -------
1       A      
1       B      
2       A      
2       B      


SELECT * FROM r_b;

CLASS   SECTION
-----   -------
1       B      
1       C      
2       B      
2       C      

我想对这两个表中的列 SECTION where CLASS=1 执行完全外连接。我想要的输出是:

SECTION SECTION_1
------- ---------
B       B        
A       (Null)   
(Null)  C        

但是,下面的查询只产生匹配的行,类似于内连接的结果。

**QUERY 1**

SELECT a.section, b.section 
FROM 
r_a a 
FULL OUTER JOIN 
r_b b 
ON a.section=b.section 
WHERE A.class=1 AND B.class=1

SECTION SECTION_1
------- ---------
B       B        

我可以通过在嵌套查询中使用 where 条件来获得所需的结果:

**QUERY 2**

SELECT a.section, b.section  
FROM
(SELECT SECTION FROM r_a WHERE class=1) a 
FULL OUTER JOIN 
(SELECT SECTION FROM r_b WHERE class=1) b
ON a.section=b.section 

SECTION SECTION_1
------- ---------
B       B        
(Null)  C        
A       (Null)   

**Query 1** 中的where 条件移至on 子句时,结果更令人惊讶:

** Query 3**

SELECT a.section, b.section 
FROM 
r_a a 
FULL OUTER JOIN 
r_b b 
ON a.section=b.section AND  A.class=1 AND B.class=1

SECTION SECTION_1
------- ---------
B       B        
(Null)  C        
(Null)  B        
(Null)  C        
B       (Null)   
A       (Null)   
A       (Null)   


MORE CLARITY:
*************

SELECT *
FROM 
r_a a 
FULL OUTER JOIN 
r_b b 
ON a.section=b.section AND  A.class=1 AND B.class=1


CLASS   SECTION CLASS_1 SECTION_1
------  ------- ------- ---------
1       B       1       B        
(Null)  (Null)  1       C        
(Null)  (Null)  2       B        
(Null)  (Null)  2       C        
2       B       (Null)  (Null)   
2       A       (Null)  (Null)   
1       A       (Null)  (Null)   

非常感谢您解释为什么 Query 1 没有产生预期的结果以及为什么 Query 3 加入 class=2,即使 on 子句说 AND A.class=1 AND B.class=1 也是如此。

【问题讨论】:

  • 这不是这些查询的输出,因为列名与代码不一致。请在代码问题中给出minimal reproducible example--剪切 & 粘贴 & 可运行代码 & 所需输出 & 明确规范 & 解释。您似乎想在 r_b 中使用不同的名称,或者在连接之前在子查询中将 section 重命名为 section_1。
  • 了解 FULL JOIN ON 返回的内容:INNER JOIN ON rows UNION ALL 不匹配的左右表行,由 NULL 扩展。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。 WHERE 或 INNER JOIN ON 在 OUTER JOIN ON 后需要右/左/两个表列不为 NULL 从由 NULL 扩展的表中删除任何行,即只留下 LEFT/RIGHT/INNER [sic] JOIN ON 行,即“将 OUTER JOIN 变为 INNER JOIN”。你有那个。

标签: oracle join full-outer-join


【解决方案1】:

您的第一个查询是 100% 完美的,只需将您的 WHERE 语句更改为 OR 而不是 AND。

SELECT a.section, b.section 
FROM 
r_a a 
FULL OUTER JOIN 
r_b b 
ON a.section=b.section 
WHERE A.class=1 OR B.class=1

这基本上就是您第二次尝试使用子查询时所做的事情。

请记住,您的 WHERE 子句是在 FROM 子句之后执行的。当您在此处使用 AND 时,您是在说“仅在两个条件都为真的连接之后获取结果”。显然,当一个表的条件 = 1 而另一个表没有时,这会转储结果。使用“或”表示“在任一条件为真的连接之后获取结果”。

【讨论】:

  • 按照你的说法返回额外的行 A.class=1, B.class=2 对于 section=B 和 A.class=2,B.class=1 对于 section=B。请自己模拟看看。
  • 问题中的输出列与其代码或您的代码不一致。
【解决方案2】:

小心,条件与条件不同:

where 是一个过滤器,在使用连接选择行后应用。 join ... on 条件并不总是在语义上等同于 where 条件。您可以查看更多详情here

您的查询 1

select asection, bsection from(
  SELECT a.section asection, b.section bsection, a.CLASS a, b.CLASS b
  FROM r_a a 
  FULL OUTER JOIN r_b b 
  ON a.section=b.section 
)
WHERE a=1 AND  b=1

【讨论】:

    猜你喜欢
    • 2016-10-02
    • 1970-01-01
    • 2017-03-22
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多