【问题标题】:Prevent Oracle minus statement from removing duplicates防止 Oracle 减号语句删除重复项
【发布时间】:2010-10-25 22:43:28
【问题描述】:

鉴于这两个表:

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”行)?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    另一种选择:

    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
    

    【讨论】:

      【解决方案2】:
      SELECT field1 FROM table1 WHERE field1 NOT IN (SELECT field2 FROM table2)
      

      只要 field2 不能包含 NULL 就可以工作。

      【讨论】:

      • 唯一的问题是,实际上我使用的减号语句不仅仅是选择单个字段(它选择了 10 个字段)。
      • 您也可以对多列执行此操作... WHERE (a,b) NOT IN (SELECT x,y FROM table2)
      【解决方案3】:

      “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),您可能会看到在这两种方法之间切换带来的性能优势。

      【讨论】:

        【解决方案4】:

        Oracle在IN语句中支持多列,所以可以这样写:

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

        【讨论】:

          【解决方案5】:

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

          select field1 from table1
          minus all
          select field2 from table2
          

          【讨论】:

          • 不。那太有意义了;)
          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:
            SELECT TEST FROM TEST1 WHERE TEST IN(
            SELECT TEST FROM TEST1
            MINUS
            SELECT TEST FROM TEST2);
            

            【讨论】:

            • 请说明您的答案是如何解决问题的,它将帮助大家更清楚地理解您的解决方案,以供将来参考。
            猜你喜欢
            • 2020-11-16
            • 2021-08-04
            • 1970-01-01
            • 1970-01-01
            • 2018-06-16
            • 2016-02-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多