用于返回非交集记录的SQL语句

时间:2017-02-10 18:21:29

标签: sql oracle11g

我最近被问到这个问题而且有点难过,所以我想问专家......

鉴于两张表A& B,我想返回A和B中不重叠的所有值。想想两个重叠的圆圈;我们如何返回不在重叠中心部分的所有数据?而且,我必须使用ANSI标准SQL而不是Oracle语法。

假设我们想要一切专属于A& B,我的回答是

  select *
  from A 
  cross join B
  minus
    (select a.common_column from a
     intersect
     select b.common_column)

这看起来是否正确,甚至是否接近?如果它是正确的,有更有效的方法吗?

BTW - 我的解决方案被彻底拒绝了......

谢谢!

6 个答案:

答案 0 :(得分:2)

鉴于表A和表B,您正在寻找(A U B) - (A& B)。换句话说,你需要一个联合B减去他们的交集。记住A和B必须是联合兼容的,才能使此查询正常工作。我愿意:

(select * from A 
 union 
 select * from B
) 
minus
(select * from A 
  intersect
 select * from B
)

答案 1 :(得分:1)

可能是全外连接?

select coalesce(A.col, B.col)
from A full outer join B on A.col = B.col
where A.col is null or B.col is null;

答案 2 :(得分:0)

要计算设定的对称差异,您可以使用MINUSUNION ALL的组合:

select * from (
  (select * from A 
   minus
   select * from B)
  union all
  (select * from B
   minus
   select * from A)
)

答案 3 :(得分:0)

您需要从两个表中选择所有数据,除非它们重叠,然后将数据与union结合起来。提供的代码应该适用于您的示例。

SELECT * 
FROM 
  (
    SELECT * FROM Table1
    EXCEPT SELECT * FROM Table2
  ) 
UNION 
SELECT * 
FROM 
  (
    SELECT * FROM Table2
    EXCEPT SELECT * FROM Table1
  )

希望这有帮助。

答案 4 :(得分:0)

您的查询被拒绝,因为它在语法上不正确:列数不同,并且会混淆cross joinunion all。但是,我认为你有正确的想法来解决这个问题。

您可以轻松解决此问题:

(select *
 from A 
 union all
 select *
 from B
) minus
(select *
 from A
 intersect
 select *
 from B
);

即,使用union all组合所有内容,然后减去两个表中出现的行。

当然,如果只有一个ID,那么您可以使用带有join的ID和其他操作。

答案 5 :(得分:0)

就像弗兰克施密特在此期间回答的那样:

这里包含一个数据示例:

WITH
table_a(name) AS (
          SELECT 'From_A_1'
UNION ALL SELECT 'From_A_2'
UNION ALL SELECT 'From_A_3'
UNION ALL SELECT 'From_A_4'
UNION ALL SELECT 'From_A_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
,
table_b(name) AS (
          SELECT 'From_B_1'
UNION ALL SELECT 'From_B_2'
UNION ALL SELECT 'From_B_3'
UNION ALL SELECT 'From_B_4'
UNION ALL SELECT 'From_B_5'
UNION ALL SELECT 'From_BOTH_6'
UNION ALL SELECT 'From_BOTH_7'
UNION ALL SELECT 'From_BOTH_8'
)
(SELECT * FROM table_a EXCEPT SELECT * FROM table_b)
UNION ALL
(SELECT * FROM table_b EXCEPT SELECT * FROM table_a)
ORDER BY name
;

name
From_A_1
From_A_2
From_A_3
From_A_4
From_A_5
From_B_1
From_B_2
From_B_3
From_B_4
From_B_5