SQL:用JOIN子句替换IN子句

时间:2017-07-24 13:29:48

标签: sql oracle

我有以下查询,我想用JOIN子句替换IN子句以提高性能。但是,当IN子句前面有一个START WITH子句时,我不知道该怎么做。我该如何解决这个问题?

SELECT * FROM t1
    INNER JOIN t2 
    ON t2.var1 = t1.var1
    WHERE var2 = 0 START WITH var3 IN
        (SELECT DISTINCT var4 FROM t3) 
    CONNECT BY var3 = PRIOR t2.var5  

我希望它看起来像这样

SELECT * FROM t1 
    INNER JOIN t2
    ON t2.var1 = t1.var1 
    WHERE var2 = 0 START WITH 
        (SELECT var3 FROM t3
        INNER JOIN 
            (SELECT DISTINCT var3 FROM t1)
        ON var3 = var4)
    CONNECT BY var3 = PRIOR t2.var5  

运行第二个查询时出现的错误是

ORA-00933: SQL command not properly ended
00933. 00000 -  "SQL command not properly ended"
*Cause:    
*Action:
Error at Line: 9 Column: 1

我猜测它是因为你必须跟START WITH使用SELECT以外的其他内容,但我不知道该怎么做。查询的其余部分是正确的(不要担心括号中的SELECT语句,它有效)。

1 个答案:

答案 0 :(得分:0)

你真的不应该做更多的工作,而不是用IN替换你的EXISTS。当您提交查询时,Oracle会执行非常高级的查询优化,并会在运行时自动将INEXISTS转换为连接。

在你的情况下:

create table t1 ( var1 number );
create table t2 ( var1 number, var2 number, var3 number, var5 number );
create table t3 ( var4 number );

insert into t1 values  ( 1 );
insert into t1 values  ( 2 );
insert into t1 values  ( 3 );

insert into t3 values ( 99 );
insert into t3 values ( 99 );  -- Duplicates in T3!
insert into t3 values ( 99 );  -- Duplicates in T3!

insert into t2 values ( 1, 0, 99, 5 );
insert into t2 values ( 1, 0, 5, 6 );
insert into t2 values ( 1, 1, 6, 7 );
insert into t2 values ( 1, 0, 7, 8 );

insert into t2 values ( 2, 0, 99, 1 );
insert into t2 values ( 2, 0, 1, 2 );
insert into t2 values ( 2, 1, 1, 3 );
insert into t2 values ( 2, 0, 3, 4 );

SELECT *
FROM   t1 INNER JOIN t2 ON t2.var1 = t1.var1
WHERE  var2 = 0
START WITH EXISTS ( SELECT 'x' FROM t3 WHERE var4 = var3 )
CONNECT BY var3 = PRIOR t2.var5 ;

计划

您可以看到它加入所有内容,然后对结果执行CONNECT BY

7 SELECT STATEMENT  ALL_ROWS
    6 FILTER  
    Filter: "T2"."VAR2"=0  
        5 CONNECT BY NO FILTERING WITH START-WITH  
        Access: "T2"."VAR3"=PRIOR "T2"."VAR5"  
        Filter: EXISTS (SELECT 0 FROM "T3" "T3" WHERE "VAR4"=:B1)  
            3 HASH JOIN  
            Access: "T2"."VAR1"="T1"."VAR1"  
                1 TABLE ACCESS FULL APPS.T1 
                2 TABLE ACCESS FULL APPS.T2 
            4 TABLE ACCESS FULL APPS.T3 
            Filter: "VAR4"=:B1