一,in
確定給定的值是否與子查詢或列表中的值相匹配。in在查詢的時(shí)候,首先查詢子查詢的表,然后將內(nèi)表和外表做一個(gè)笛卡爾積,然后按照條件進(jìn)行篩選。所以相對內(nèi)表比較小的時(shí)候,in的速度較快。
具體sql語句如下
SELECT
*
FROM
user
WHERE
user.id IN (
SELECT
order.user_id
FROM
order
)
它的執(zhí)行流程是什么樣子的呢?讓我們一起來看一下。
1, SELECT
order.user_id
FROM
order
2,將查詢到的結(jié)果和原有的user表做一個(gè)笛卡爾積
二,exists
指定一個(gè)子查詢,檢測行的存在。遍歷循環(huán)外表,然后看外表中的記錄有沒有和內(nèi)表的數(shù)據(jù)一樣的。匹配上就將結(jié)果放入結(jié)果集中。
具體sql語句如下:
SELECT
user.*
FROM
user
WHERE
EXISTS (
SELECT
order.user_id
FROM
order
WHERE
user.id = order.user_id
)
首先,我們先查詢的不是子查詢的內(nèi)容,而是查我們的主查詢的表,也就是說,我們先執(zhí)行的sql語句是:
1,SELECT user.* FROM user
2,EXISTS (
SELECT
order.user_id
FROM
order
WHERE
user.id = order.user_id
)
三,區(qū)別及應(yīng)用場景
in 和 exists的區(qū)別: 如果子查詢得出的結(jié)果集記錄較少,主查詢中的表較大且又有索引時(shí)應(yīng)該用in, 反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時(shí)使用exists。其實(shí)我們區(qū)分in和exists主要是造成了驅(qū)動順序的改變(這是性能變化的關(guān)鍵),如果是exists,那么以外層表為驅(qū)動表,先被訪問,如果是IN,那么先執(zhí)行子查詢,所以我們會以驅(qū)動表的快速返回為目標(biāo),那么就會考慮到索引及結(jié)果集的關(guān)系了 ,另外IN時(shí)不對NULL進(jìn)行處理。
in 是把外表和內(nèi)表作hash 連接,而exists是對外表作loop循環(huán),每次loop循環(huán)再對內(nèi)表進(jìn)行查詢。一直以來認(rèn)為exists比in效率高的說法是不準(zhǔn)確的。
四,on與where
1、 on條件是在生成臨時(shí)表時(shí)使用的條件,它不管on中的條件是否為真,都會返回左邊表中的記錄。
2、where條件是在臨時(shí)表生成好后,再對臨時(shí)表進(jìn)行過濾的條件。這時(shí)已經(jīng)沒有l(wèi)eft join的含義(必須返回左邊表的記錄)了,條件不為真的就全部過濾掉