防止Oracle减去语句删除重复项

时间:2009-05-13 17:18:31

标签: sql oracle

鉴于这两个表:

CREATE TABLE TEST1 (TEST  VARCHAR2(1 BYTE))
CREATE TABLE TEST2 (TEST  VARCHAR2(1 BYTE))

其中TEST1有两行,值均为“A”,而TEST2的行为一行,值为“B”。

当我运行此命令时:

SELECT TEST FROM TEST1
MINUS
SELECT TEST FROM TEST2

我得到了输出:

Test
-----
A

似乎MINUS删除了重复项(因为TEST1中有两个'A'行)。

如何让MINUS查询包含重复值(返回两个'A'行)?

7 个答案:

答案 0 :(得分:8)

另一种选择:

SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST1
MINUS
SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST2

这将是MINUS,每个副本都被视为一个独特的条目。请注意,在下面的示例中,如果TEST1有两个'C'值而TEST2只有一个,那么输出中就有一个。

dev> select * from test1;

T
-
A
A
B
C
C

dev> select * from test2;

T
-
B
C

dev>     SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST1
  2      MINUS
  3      SELECT TEST, row_number() OVER (PARTITION BY TEST ORDER BY TEST) FROM TEST2
  4  /

T ROW_NUMBER()OVER(PARTITIONBYTESTORDERBYTEST)
- --------------------------------------------
A                                            1
A                                            2
C                                            2

答案 1 :(得分:1)

SELECT field1 FROM table1 WHERE field1 NOT IN (SELECT field2 FROM table2)
只要field2不能包含NULL,

就会工作。

答案 2 :(得分:1)

“NOT IN”答案都是正确的。对于某些场景可能更容易的替代方案是“NOT EXISTS”运算符:

SELECT TEST FROM TEST1
WHERE NOT EXISTS
(SELECT null FROM TEST2 WHERE TEST2.TEST = TEST1.TEST);

(注意:select子句中的“null”在这里没有意义)

我个人使用这两种方法,但我喜欢NOT EXISTS,因为它更灵活 - 例如,它不要求比较处于相等条件。

最新版本的优化器通常会将NOT IN转换为NOT EXISTS,反之亦然;但是,如果您使用的是旧版本(例如8i甚至9i),您可能会看到通过这两种方法之间切换带来的性能优势。

答案 3 :(得分:0)

ALL修饰符使UNION返回所有行(例如,UNION ALL),也许它可以应用于MINUS?如在

select field1 from table1
minus all
select field2 from table2

答案 4 :(得分:0)

减号的一部分是删除重复项。考虑使用NOT IN来避免删除重复项。

SELECT TEST FROM TEST1 WHERE TEST NOT IN(SELECT TEST FROM TEST2)

答案 5 :(得分:0)

Oracle支持IN语句中的多个列,因此您可以编写:

SELECT a, b, c
FROM table1
WHERE (a,b,c) not in (
    select a,b,c from table2
)

答案 6 :(得分:0)

CompletableFuture