MySQL子查詢(一)—— EXISTS與IN
原文:http://www.innomysql.net/article/69.html
EXISTS是一個非常強大的謂詞,它允許資料庫高效地檢查指定查詢是否產生某些行。通常EXISTS的輸入是一個子查詢,並關聯到外部查詢,但這並不一定是必須的。根據子查詢是否返回行,該謂詞返回TRUE或FALSE。例如下面的SQL語句:
1 2 3 4 5 6 |
SELECT
customerid,companyname
FROM
customers AS
A
WHERE
country = 'Spain' AND
EXISTS
( SELECT
* FROM
orders AS
B
WHERE
A.customerid = B.customerid )
|
通過下圖的查詢計劃可以發現,SQL優化器首先根據WHERE條件先將country列為Spain的行資料取出,對於每個匹配的customerid,該執行計劃對orders表上customerid索引進行一次查詢,以檢查orders表中是否有customerid的訂單。子查詢中的索引是非常必須的,因為這可以加速對於表orders的訪問。
上述的SQL語句可以重寫為IN子查詢,並且兩者的查詢計劃是相同的:
1 2 3 4 |
SELECT
customerid,companyname
FROM
customers AS
A
WHERE
country = 'Spain'
AND
customerid IN
( SELECT
customerid FROM
orders );
|
實際在MySQL 5.6版本之前,其對於IN語句的優化是“LAZY”的。這意味著對於IN子句,如果不是顯示的列表定義,如IN (‘a’,’b‘,’c‘),那麼IN子句都會被轉換為EXISTS的相關子查詢。如下這句獨立子查詢:
1 |
SELECT
... FROM
t1 WHERE
t1.a IN
( SELECT
b FROM
t2);
|
優化器會將該語句重寫為如下的相關子查詢:
1 2 |
SELECT
... FROM
t1
|