从查询中消除NOT IN

Bat*_*man 2 sql oracle

我正在尝试消除NOT IN在查询中使用的需要:

select count(*) 
FROM TABLE1 T1
LEFT OUTER JOIN TABLE2 T2
    ON T1.DATAID = T2.EXISTING_DOCUMENT
        AND T1.ownerid = -2000 
        AND T1.SUBTYPE = 144 
        AND T1.dataid NOT IN (SELECT T3.dataid 
                           FROM   TABLE3 T3
                           WHERE  T3.ID = 123)
Run Code Online (Sandbox Code Playgroud)

原因:我读的NOT IN很慢(+ 500k行)并且不使用索引

我试过了:

select count(*) 
FROM TABLE1 T1 
LEFT OUTER JOIN TABLE2 T2 
ON T1.DATAID = T2.EXISTING_DOCUMENT
        AND T1.ownerid = -2000 
        AND T1.SUBTYPE = 144 
left outer join TABLE3 T3 
 on T3.ancestorid = T1.dataid
    where T3.ID = 123
Run Code Online (Sandbox Code Playgroud)

Gor*_*off 5

NOT IN确实使用索引,至少在一个称职的数据库中如Oracle.但是,join如果您愿意,可以使用s 来编写.

但是,为什么这不是你想做的?

select count(*) 
FROM TABLE1 T1
WHERE T1.ownerid = -2000 AND T1.SUBTYPE = 144;
Run Code Online (Sandbox Code Playgroud)

你正在使用a LEFT JOIN,所以唯一的区别是你的版本重复了TABLE2.但这可能并不适用.

您的查询并没有真正意义的,因为你是比较T1.dataidT1.dataid.但是,进一步说,比较对Table3结果没有影响.所以,你可以删除它:

select count(*) 
FROM TABLE1 T1 LEFT OUTER JOIN
     TABLE2 T2
     ON T1.DATAID = T2.EXISTING_DOCUMENT AND
        T1.ownerid = -2000 AND
        T1.SUBTYPE = 144 ;
Run Code Online (Sandbox Code Playgroud)

因为,子句中的LEFT JOIN过滤ON不会删除任何行.因为它是NOT IN,所以不可能有重复.