原創做品,能夠轉載,可是請標註出處地址http://www.cnblogs.com/V1haoge/p/6385312.htmlhtml
咱們在程序中通常在作SQL優化的時候講究使用EXISTS帶替代IN的作法,理由是EXISTS執行效率要比IN高。
以前我一直挺懵懂的一件事情是如何使用EXISTS來替換IN呢,兩者表示的意義又是什麼呢?今天就我我的理解記錄一下
IN表示範圍,指某一字段在某一範圍以內,這個範圍通常使用子查詢來獲取,由此可知IN子查詢返回的結果應該就是這個範圍集。
EXISTS表示存在,指至少存在一處,這個條件由EXISTS子查詢來完成,可是在這裏EXISTS子查詢返回的結果卻再也不是一個結果集,而是一個布爾值(true或false),其實這個挺好理解的,EXISTS就表示若是子查詢能查到值則返回true,則執行EXISTS以前的語句。
舉個栗子
假若有一個表user,它有兩個字段id和name,咱們要查詢名字中帶a的用戶信息:
最簡單的SQL:select * from user where name like '%a%';
使用IN的SQL:select u.* from user u where u.id in (select uu.id from user uu where uu.name like '%a%');
咱們如今將使用IN的SQL修改成使用EXISTS的SQL該怎麼寫呢?
一開始我直接將u.id in 替換爲EXISTS,得到以下語句 :
select u.* from user u where exists(select uu.id from user uu where uu.name like '%a%');
通過測試發現輸出結果錯誤,該語句將全部的用戶所有一個不漏的查詢出來了,相信你也發現了問題,後來我對上述語句作了修改以下:
select u.* from user u where exists (select uu.id from user uu where uu.name like '%a%' and uu.id=u.id);
如你所見,只是在子查詢中添加了「and uu.id=u.id」,結果查詢結果正確。
那麼緣由爲什麼呢?
總結:EXISTS子查詢能夠當作是一個獨立的查詢系統,只爲了獲取真假邏輯值,EXISTS子查詢與外查詢查詢的表是兩個徹底獨立的毫無關係的表(當第二個表中的name中有包含a的姓名存在,那麼就執行在第一個表中查詢全部用戶的操做),當咱們在子查詢中添加了id關聯以後,EXISTS子查詢與外查詢查詢的表就統一了,是兩者組合組建的虛表,是同一個表(這樣當子查詢查詢到虛表中當前行的uu.name中包含a時,則將虛表當前行中對應的u.id與u.name查詢到了)
因此一切的重點就在這個ID關聯之上,添加ID關聯,數據庫會先將兩張表經過ID關聯組合成一張虛表,全部的查詢操做都在這張虛表上完成,操做的是同一張表,固然就不會出現以前的那種狀況了!數據庫