WHERE 子句中的標量子查詢
標量子查詢不僅可以用在SELECT 語句的列表中,它還可以用在WHERE 子句中,而且實際應用中子查詢很多的時候都是用在WHERE子句中的。
先來看一個簡單的例子,我們要檢索喜歡“Story”的讀者主鍵列表,那麼這可以使用連線來完成,不過這裡我們將使用子查詢來完成。
使用子查詢的實現思路也比使用連線簡單。首先肯定要到T_Category 表中查詢FName等於“Story”的記錄的FId欄位值:
SELECT FId FROM T_Category WHERE FName=" Story "
因為這個查詢的返回值是單列且單行的,所以可以當作標量子查詢使用。將這個子查詢結果來構造外部查詢:
SELECT FReaderId FROM T_ReaderFavorite WHERE FCategoryId=(SELECT FId FROM T_Category WHERE FName="Story")
執行這個SQL語句則會得到下面的執行結果:
FReaderId
1
6
7
12
3
下面來看一個稍微複雜一點的例子。假設需要檢索每一種書籍類別中出版年份最早的書籍的名稱,如果有兩本或者多本書籍在同一年出版,則均顯示它們的名字。要求檢索結果中顯示出型別的名字、書的名字和它的出版年份。
檢索每種型別圖書中出版時間最早的圖書非常簡單,只要使用GROUP BY 子句以及聚合函式就可以輕鬆完成這個任務,SQL語句如下:
SELECT T_Category.FId,MIN(T_Book.FYearPublished) FROM T_Category INNER JOIN T_Book ON T_Category.FId=T_Book.FCategoryId GROUP BY T_Category.FId
執行完畢我們就能在輸出結果中看到下面的執行結果:
FId
1 1999
2 1700
3 1930
4 2003
5 1771
6 1995
查詢結果是正確的,不過這個查詢結果沒有提供書名,只提供了型別主鍵和出版時間最早的圖書的出版年份。嘗試將圖書的名字加入到SELECT語句中,如下:
SELECT T_Category.FId, T_Book. FName,MIN(T_Book.FYearPublished) FROM T_Category INNER JOIN T_Book ON T_Category.FId=T_Book.FCategoryId GROUP BY T_Category.FId
在資料庫系統中執行這個SQL語句會報出如下的錯誤資訊:
- 選擇列表中的列"T_Book.FName" 無效,因為該列沒有包含在聚合函式或GROUP BY子句中。
出現這個錯誤的原因是所有在SELECT列表中的欄位如果沒有包含在聚合函式中,則必須放到GROUP BY 子句中,所以將T_Book. FName加入到GROUP BY 子句中,修改後的SQL語句如下:
SELECT T_Category.FId, T_Book. FName,MIN(T_Book.FYearPublished) FROM T_Category INNER JOIN T_Book ON T_Category.FId=T_Book.FCategoryId GROUP BY T_Category.FId, T_Book. FName
執行完畢我們就能在輸出結果中看到下面的執行結果:
FId FName
1 Jane Eyre 2001
1 Oliver Twist 2002
1 Two Cites 1999
2 History of America 1700
2 History of China 1982
2 History of England 1860
2 History of TheWorld 2008
3 Astronomy 1971
3 Atom 1930
3 Computer 1970
3 RELATIVITY 1945
4 About J2EE 2005
4 Learning Hibernate 2003
5 How To Singing 1771
6 DaoDeJing 2001
6 Obedience to Authority 1995
這個執行結果顯然是錯誤的,因為它們是根據T_Category.FId和T_Book.FName這兩個欄位進行的分組,所以MIN(T_Book.FYearPublished)返回值不是一個特定書籍型別的最早出版年份,而是每本圖書中的最早出版年份。而真正需要的是查詢每種書籍型別中的最早出版的書籍,可以使用子查詢來輕鬆完成這個任務。在SQL查詢中,需要將一本書籍的出版年份與該型別的所有書籍的出版年份進行比較,並且僅僅在它們匹配時,才返回一個記錄,實現SQL語句如下:
SELECT T_Category.FId, T_Book. FName,T_Book.FYearPublished FROM T_Category INNER JOIN T_Book ON T_Category.FId=T_Book.FCategoryId WHERE T_Book.FYearPublished=(SELECT MIN(T_Book.FYearPublished) FROM T_Book WHERE T_Book.FCategoryId=T_Category.FId)
在這個SQL語句中,T_Category表和T_Book表首先進行內部連線,然後使用WHERE子句中使用子查詢來進行資料的過濾。這個子查詢是一個相關子查詢,它返回外部查詢中當前圖書類別中的圖書的最早出版年份。在外部查詢的WHERE子句中,T_Book的FYearPublished與子查詢的返回值進行比較,這樣就可以得到每種書籍型別中的出版最早的書籍了。
執行完畢我們就能在輸出結果中看到下面的執行結果:
FId FName FYearPublished
1 Two Cites 1999
2 History of America 1700
3 Atom 1930
4 Learning Hibernate 2003
5 How To Singing 1771
6 Obedience to Authority 1995