日期:2014-05-16 浏览次数:20436 次
典型的查询方式为:
SELECT TITLE
FROM BOOKSHELF
WHERE TITLE NOT IN
????? (SELECT TITLE FROM BOOKSHELF_CHECKOUT)
ORDER BY TITLE;
如果BOOKSHELF_CHECKOUT很大的话,速度可能会很慢,因为ORACLE会在BOOKSHELF_CHECKOUT上执行一个时间密集型的全表扫描。
oracle 中not in 效率不高
一:
使用外部连接?
SELECT DISTINCT C.TITLE
FROM BOOKSHELF_CHECKOUT B RIGHT OUTER JOIN BOOKSHELF C
??? ON B.TITLE = C.TITLE
WHERE B.TITLE IS NULL
ORDER BY C.TITLE ;
优化后的程序可以使用连接列上的索引。
WHERE B.TITLE IS NULL?
表示不出现在BOOKSHELF_CHECKOUT中的TITLE列 (ORACLE作为NULL列返回,可参考外部连接方面的内容)
二:
使用NOT EXISTS?
SELECT B.TITLE?
FROM BOOKSHELF B
WHERE NOT EXISTS
???? (SELECT 'X' FROM BOOKSHELF_CHECKOUT C
????? WHERE C.TITLE = B.TITLE)
ORDER BY B.TITLE
对于BOOKSHELF中每一个记录和BOOKSHELF_CHECKOUT匹配则是EXISTS.NOT EXISTS则是不存在的。?
NOT EXISTS往往可以使用可利用的索引,NOT IN 可能无法使用这些索引。
?
exists (sql 返回结果集为真)?
not exists (sql 不返回结果集为真)?
如下:?
表A?
ID NAME?
1??? A1?
2??? A2?
3? A3
表B?
ID AID NAME?
1??? 1 B1?
2??? 2 B2?
3??? 2 B3
表A和表B是1对多的关系 A.ID => B.AID
SELECT ID,NAME FROM A WHERE EXIST (SELECT * FROM B WHERE A.ID=B.AID)?
执行结果为?
1 A1?
2 A2?
原因可以按照如下分析?
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=1)?
--->SELECT * FROM B WHERE B.AID=1有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=2)?
--->SELECT * FROM B WHERE B.AID=2有值返回真所以有数据
SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=3)?
--->SELECT * FROM B WHERE B.AID=3无值返回真所以没有数据
NOT EXISTS 就是反过来?
SELECT ID,NAME FROM A WHERE NOT EXIST (SELECT * FROM B WHERE A.ID=B.AID)?
执行结果为?
3 A3?
===========================================================================?
EXISTS = IN,意思相同不过语法上有点点区别,好像使用IN效率要差点,应该是不会执行索引的原因?
SELECT ID,NAME FROM A WHERE ID IN (SELECT AID FROM B)
NOT EXISTS = NOT IN ,意思相同不过语法上有点点区别?
SELECT ID,NAME FROM A WHERE ID NOT IN (SELECT AID FROM B)