【MySQL】子查詢之一

楊奇龍發表於2013-09-15
MySQL 從版本4 開始支援 SQL 標準要求的所有子查詢格式和操作,同時擴充套件了特有的幾種特性。本文會介紹子查詢的型別以及相關的注意點。
一 什麼是子查詢
    子查詢是將一個 SELECT 語句的查詢結果作為中間結果,供另一個 SQL 語句呼叫。如:
SELECT * FROM t1  WHERE vid in  (SELECT  vid FROM t2);

二 MySQL 子查詢分類
      根據子查詢的返回資料形式,mysql 子查詢可以分為以下幾類:

a  標量子查詢
     標量子查詢是指子查詢返回的是單一值的標量,如一個數字或一個字串,也是子查詢中最簡單的返回形式。
SELECT * FROM article WHERE uid = (SELECT uid FROM user WHERE status=1 ORDER BY uid DESC LIMIT 1);
使用子查詢進行比較
可以使用 = > < >= <= <> 這些運算子對子查詢的標量結果進行比較,通常子查詢的位置在比較式的右側:
SELECT * FROM t1 WHERE vid = (SELECT MAX(col2) FROM t2);

b 列子查詢
   列子查詢是指子查詢返回的結果集是 N 行一列,該結果通常來自對錶的某個欄位查詢返回。
一個列子查詢的例子如下:
SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=1);

c 行子查詢
   行子查詢是指子查詢返回的結果集是一行 N 列,該子查詢的結果通常是對錶的某行資料進行查詢而返回的結果集。
一個行子查詢的例子如下:
SELECT * FROM table1 WHERE (1,2) = (SELECT vid, col2 FROM table2)
   在該例子中,在保證子查詢返回單一行資料的前提下,如果 vid=1 且 col2=2 ,則該查詢結果為 TRUE。
MySQL 行構造符 
    在上面的例子中,WHERE 後面的 (1,2) 被稱為行構造符,也可以寫為ROW(1,2)。行構造符通常用於與對能返回兩個或兩個以上列的子查詢進行比較。

d FROM 子句中的子查詢
   MySQL FROM 子查詢是指 FROM 的子句作為子查詢語句,主查詢再到子查詢結果中獲取需要的資料。FROM 子查詢語法如下:
SELECT ... FROM (subquery) AS name ...
子查詢會生成一個臨時表,由於 FROM 子句中的每個表必須有一個名稱,因此 AS name 是必須的。FROM 子查詢也稱為衍生資料表子查詢。

注意
MySQL FROM 子句中的子查詢可以返回標量、列、行或表,但不能為有關聯的子查詢。

e 表子查詢
    表子查詢是指子查詢返回的結果集是 N 行 N 列的一個表資料。
SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog)
該 SQL 的意義在於查詢 article 表中指定的欄位同時也存在於 blog 表中的所有的行(注意 = 比較運算子換成了 IN),實際上等同於下面的條件語句:
SELECT * FROM article,blog 
WHERE (article.title=blog.title AND article.content=blog.content AND article.uid=blog.uid)
實際上,很多 in 的子查詢都可以修改為 join方式和關聯查詢,而且相比而言後面的效率更高。

f MySQL EXISTS 和 NOT EXISTS 子查詢
其語法如下:
SELECT ... FROM table WHERE  EXISTS (subquery)
該語法可以理解為:
將主查詢的資料,放到子查詢中做條件驗證,根據驗證結果(TRUE 或 FALSE)來決定主查詢的資料結果是否得以保留。

注意:
  1 EXISTS (subquery) 只返回 TRUE 或 FALSE,因此子查詢中的 SELECT * 也可以是 SELECT 1 或其他,官方說法是實際執行時會忽略 SELECT 清單,因此沒有區別。
  2 EXISTS 子查詢的實際執行過程可能經過了最佳化而不是我們理解上的逐條對比,如果擔憂效率問題,可進行實際檢驗以確定是否有效率問題。
  3 EXISTS 子查詢往往也可以用條件表示式、其他子查詢或者 JOIN 來替代,何種最優需要具體問題具體分析。

g MySQL 關聯子查詢
        關聯子查詢通俗一點來講,就是子查詢引用到了主查詢的資料資料。
以一個實際的例子來理解關聯子查詢:
SELECT * FROM article WHERE uid IN (SELECT uid FROM user WHERE article.uid = user.uid);
但在關聯子查詢中,是無法單獨執行子查詢語句的。其實際流程大致為:
    1 先做外部主查詢;
    2 將主查詢的值傳入子查詢並執行;
    3 子查詢再將查詢結果返回主查詢,主查詢根據返回結果完成最終的查詢。
 這個執行流程類似於 EXISTS 子查詢,實際上某些情況下 MySQL 就是將關聯子查詢重寫為 EXISTS 子查詢來執行的。

三  小結
      上文簡單介紹了子查詢的常見用法,但是生產環境中僅僅知道用法還是不夠的,mysql 本身的子查詢機制(將在下文介紹)使得dba在生產環境中使用子查詢是必須謹慎。
   
參考 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-772726/,如需轉載,請註明出處,否則將追究法律責任。

相關文章