1. 程式人生 > >[置頂] 子查詢改為左連結

[置頂] 子查詢改為左連結

子查詢是一個 SELECT 查詢,它巢狀在 SELECT、INSERT、UPDATE、DELETE 語句或其它子查詢中。
  任何允許使用表示式的地方都可以使用子查詢,子查詢可以使我們的程式設計靈活多樣,可以用來實現一些特殊的功能。但是在效能上,往往一個不合適的子查詢用法會形成一個性能瓶頸。如果子查詢的條件中使用了其外層的表的欄位,這種子查詢就叫作相關子查詢。


相關子查詢可以用IN、NOT IN、EXISTS、NOT EXISTS引入。 關於相關子查詢,應該注意:
(1) NOT IN、NOT EXISTS的相關子查詢可以改用LEFT JOIN代替寫法。比如:

SELECT PUB_NAME FROM PUBLISHERS WHERE PUB_ID NOT IN (SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')

可以改寫成:
SELECT A.PUB_NAME FROM PUBLISHERS A LEFT JOIN TITLES B ON B.TYPE ='BUSINESS'AND A.PUB_ID=B. PUB_ID WHERE B.PUB_ID IS NULL
  
比如NOT EXISTS:
SELECT TITLE FROM TITLES  WHERE NOT EXISTS  (SELECT TITLE_ID FROM SALES WHERE TITLE_ID = TITLES.TITLE_ID)
可以改寫成:
SELECT TITLE  FROM TITLES LEFT JOIN SALES  ON SALES.TITLE_ID = TITLES.TITLE_ID  WHERE SALES.TITLE_ID ISNULL

2)如果保證子查詢沒有重複 ,IN、EXISTS的相關子查詢可以用INNER JOIN 代替。比如:
SELECT PUB_NAME  FROM PUBLISHERS  WHERE PUB_ID IN  (SELECT PUB_ID  FROM TITLES  WHERE TYPE ='BUSINESS')
可以改寫成:
SELECT DISTINCT A.PUB_NAME  FROM PUBLISHERS  A JOIN TITLES  B ON A. PUB_ID=B. PUB_ID WHERE B. TYPE ='BUSINESS'

  •  LEFT JOIN 和 is null 的理解

SELECT *  from  t1   LEFT JOIN t2   ON   t1.id=t2.id     WHERE t2.id IS NULL;
假定t2.id定義為NOT NULL。在這種情況下,MySQL使用t1.id的值掃描t1並查詢t2中的行。
如果MySQL在t2中發現一個匹配的行,它知道t2.id絕不會為NULL,並且不再掃描t2內有相同的id值的行。
換句話說,對於t1的每個行,MySQL只需要在t2中查詢一次,無論t2內實際有多少匹配的行。
當通過t1掃描查詢到t2記錄時,後面的where條件不成立,所以t1停止查詢。

當通過t1掃描沒有查詢到t2記錄時,t2.id自然為空,後面的where條件成立,返回的結果就是不在t2中的記錄。

  • 查詢邏輯順序

在學生成績表中 (暫記為 tb_Grade),“考生姓名”內容不為空的記錄按照“考生姓名”分組,並且篩選分組結果,選出“總成績”大於 600分的,標準順序的 SQL語句為:

select考生姓名, max(總成績) as max總成績

from tb_Grade

where考生姓名 is not null

group by考生姓名

having max(總成績) > 600

order by max總成績

在上面的示例中 SQL語句的執行順序如下:

(1).首先執行 FROM子句, tb_Grade表組裝資料來源的資料

(2).執行 WHERE子句,篩選 tb_Grade表中所有資料不為 NULL的資料

(3).執行 GROUP BY子句, tb_Grade表按“學生姓名”列進行分組

(4).計算 max()聚集函式,“總成績”求出總成績中最大的一些數值

(5).執行 HAVING子句,篩選課程的總成績大於 600分的.

(7).執行 ORDER BY子句,把最後的結果按Max成績”進行排序.