我有以下查询,我想用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
语句,它有效)。
答案 0 :(得分:0)
你真的不应该做更多的工作,而不是用IN
替换你的EXISTS
。当您提交查询时,Oracle会执行非常高级的查询优化,并会在运行时自动将IN
和EXISTS
转换为连接。
在你的情况下:
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