NOT EXISTS无效的关系运算符

时间:2012-11-27 14:06:12

标签: sql oracle

我有一个类似于以下列的表:bad_mrn,good_mrn,cr_date

insert into mrn_merge values ( '00000001','00000002', '20121120');
insert into mrn_merge values ( '00000002','00000003', '20121120');
insert into mrn_merge values ( '00000003','00000004', '20121120');

所以最后。
- 1合并为2
- 2合并为3
- 3合并为4

如果我提供的输入参数为1,2,3或4,我需要一个返回4的查询。 以下准备好的语句确实有效,但是当我的mrn_merge表开始有40k记录时,它会让位。

SELECT *
FROM
   (SELECT good_mrn, LEVEL
    FROM mrn_merge
    WHERE 
        (CONNECT_BY_ROOT bad_mrn =
            (SELECT bad_mrn FROM mrn_merge WHERE LEVEL =
                (SELECT MAX (LEVEL) FROM mrn_merge  START WITH good_mrn = ?
                 CONNECT BY PRIOR bad_mrn = good_mrn )
             START WITH good_mrn = ?
             CONNECT BY PRIOR bad_mrn = good_mrn)
        )  OR ( CONNECT_BY_ROOT bad_mrn = ?)
    START WITH  bad_mrn NOT IN ( SELECT good_mrn FROM mrn_merge  )
    CONNECT BY bad_mrn = PRIOR good_mrn  ORDER BY LEVEL DESC)
WHERE ROWNUM = 1 ;

sql tuning advisor说使用“NOT EXISTS”代替“NOT IN”但是我得到了ORA-00920:无效的关系运算符 00920. 00000 - “无效的关系运营商”..

感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:1)

您不能简单地将NOT IN换成NOT EXISTS

NOT IN针对子查询的结果测试一个列(或用括号括起来的一组列),该子查询必须返回相同数量的列。

SELECT a.cols
FROM table_a a
WHERE a.id NOT IN (
  SELECT b.id
  FROM table_b b
)

SELECT a.cols
FROM table_a a
WHERE (a.id, a.name) NOT IN (
  SELECT b.id, b.name
  FROM table_b b
)

NOT EXISTS测试子查询是返回零行(TRUE)还是返回一行或多行(FALSE)。通常,子查询与外部查询相关,即子查询内的列(或列集)将针对外部查询中的列(或列集)进行测试。

SELECT a.cols
FROM table_a a
WHERE NOT EXISTS (
  SELECT 1
  FROM table_b b
  WHERE b.id = a.id
)

在您的具体示例中,我似乎并不认为您可以合理地重写使用NOT EXISTS的子句。

答案 1 :(得分:0)

如果有人看到这个感谢..但是,我的DBA能够挤进我帮助这个查询..答案是让它更简单,更有效..

  

从中选择good_mrn(选择good_mrn,CONNECT_BY_ROOT bad_mrn,cr_date,bad_mrn
    来自mrn_merge从good_mrn开始=?或bad_mrn =?
    通过bad_mrn =先前的good_mrn连接,其中good_mrn不在    (从mrn_merge中选择bad_mrn)和rownum< = 1;

现在它运行效率非常高。谢谢..