与Oracle中的INTERSECT相反

时间:2009-10-20 07:47:55

标签: sql oracle

我有两个选择,我想以这样的方式组合它们,只返回两个选择中唯一的行。 Oracle 10g中是否有任何内置方法可以实现此目的?

我知道我可以这样做:

(select1 UNION select2)
MINUS
(select1 INTERSECT select2)

但我想避免它。 select1select2都有20行,所以这种方式非常模糊,难以维护。

6 个答案:

答案 0 :(得分:8)

如果select1select2都没有重复,您可以使用以下内容:

SELECT * FROM (select1 UNION ALL select2) a
GROUP BY a.col1, a.col2, ...
HAVING count(*) = 1

答案 1 :(得分:3)

在Oracle 10g中,您可以使用Common Table Expressions。

WITH
  select_1 AS (
    SELECT *
    FROM your_table
    WHERE your_condition = 1
  ),
  select_2 AS (
    SELECT *
    FROM your_other_table
    WHERE your_other_condition = 1
  )
SELECT * FROM select_1
UNION
SELECT * FROM select_2
MINUS
(
  SELECT * FROM select_1
  INTERSECT
  SELECT * FROM select_2
);

这样可以保持子查询的可维护性,并使最终查询的目的明确。

当然,让Oracle向SQL添加SYM_DIFFERENCE运算符会更好,但我不会屏住呼吸 - 他们仍然不相信BOOLEAN数据类型是个好主意

答案 2 :(得分:2)

这是另一个想法:

  • 执行select1和select2
  • 的完整外连接
  • 仅使用select1.id = NULL的记录(记录仅在select2中)或select2.ID = NULL(记录仅在select1中)
像这样:

SELECT *
FROM select1 FULL OUTER JOIN select2 on select1.id = select2.id
WHERE select1.id is null or select2.id is null

答案 3 :(得分:1)

这对我有用 - 不确定它有多快。

(select table_name from dba_tables where user = 'X'
union
select table_name from dba_tables where user = 'Y')
minus
(select table_name from dba_tables where user = 'X'
intersect
select table_name from dba_tables where user = 'Y')

答案 4 :(得分:0)

-- get not intersect data
SELECT_FINAL
WHERE FIELD_PK IS NOT IN(
    -- get ids of intersect
    SELECT_AUX FIELD_PK1 FROM (
        SELECT1
        INTERSECT
        SELECT2
     )
)

我这样做

答案 5 :(得分:0)

这是另一种解决方案,这次使用count()分析(Oracle 10或更高版本)。

优点:

  • 我们可以指定哪些列为EXTRASECT(例如示例中的KK1,KK2)。
  • 我们可以选择我们不需要匹配的非关键列(例如NK1,NK2 ......)。
  • 高效计划。
  • 与FULL OUTER JOIN示例类似,但我们不会将关键列作为需要解码或大小写的单独字段将它们折叠在一起。

select KK1, KK2, NK1, NK2 from ( select KK1, KK2, NK1, NK2, count( * ) over( partition by KK1, KK2 ) cnt from ( select KK1, KK2, NK1, NK2 from X union all select KK1, KK2, NK1, NK2 from Y ) ) where cnt = 1;

相关问题