李增祥
摘要:相關(guān)子查詢是那些能夠表不可能為可能的事物之一,此外,它們經(jīng)常把幾行代碼變成一行,并且?guī)硐鄳阅艿奶嵘?,伴隨相關(guān)子查詢的問題是,它們通常需要有別于常規(guī)的徹底不同的思維方式,相關(guān)子查詢在SQL學習中是最容易學會的概念,但也是最容易被遺忘的概念,因為相關(guān)子查詢與正常的思維方式正好相反,本文介紹相關(guān)子查詢的概念,以及如何在WHERE字句和SELECT子句中使用相關(guān)子查詢,如果掌握這兩點,當需要從查詢中尋找所有的性能時,將會成為非常好的工具。
關(guān)鍵詞:相關(guān)子查詢;WHERE;SELECT
中國分類號:G712? ? ? ? ? 文獻標識碼:A
文章編號:1009-3044(2019)23-0005-02
開放科學(資源服務)標識碼(OSID):
SQL子查詢可以分為 相關(guān)子查詢和嵌套子查詢兩類,嵌套子查詢的執(zhí)行不依賴與外部的查詢[1],它的執(zhí)行過程是先執(zhí)行子查詢,其結(jié)果不被顯示,而是傳遞給外部查詢,作為外部查詢的條件使用;然后再執(zhí)行外部查詢,并顯示整個結(jié)果。嵌套子查詢一般可以分為兩種,一種是返回單值的子查詢,另外一種則是返回一個列表的子查詢。相關(guān)子查詢的執(zhí)行依賴于外部查詢,多數(shù)情況下是子查詢的WHERE子句中引用了外部查詢的表。
1相關(guān)子查詢的概念
相關(guān)子查詢是一種其內(nèi)部查詢和外部查詢相互交叉的數(shù)據(jù)檢索方法.在相關(guān)子查詢中[2],信息是雙向而非單向進行的,內(nèi)部查詢根據(jù)外部查詢提供的信息執(zhí)行,反之亦然,從概念上講包含相關(guān)子查詢的語句在執(zhí)行時部能分為一先一后兩個步驟,首先外部查詢得到一條記錄并將其傳入到內(nèi)部查詢,內(nèi)部查詢基于剛剛傳入的值執(zhí)行,然后內(nèi)部查詢從其結(jié)果中把值傳回到外部查詢[3],通過外部查詢使用這些值來完成其處理。也就是說,相關(guān)子查詢無法獨立于外部查詢進行計算,因為內(nèi)部查詢使用了外部語句的值。即,會針對外部語句中的每一行來執(zhí)行內(nèi)部查詢[4]。因此,內(nèi)部查詢的結(jié)果取決于外部語句中正在計算的活動行。
2 Select列表中的相關(guān)子查詢
子查詢也能用來在選擇結(jié)果中提供一種不同類型的答案。這種情形通常出現(xiàn)在要找尋的信息與查詢中的其他數(shù)據(jù)全然不同的時候(例如,當想要在一個字段上進行聚集,但卻不希望因此而影響返回的其他字段)。
為了實驗,我們需要創(chuàng)建一個數(shù)據(jù)庫Works,假設我們要在數(shù)據(jù)庫Works中查找的是顧客的名字以及首次訂購的日期,數(shù)據(jù)庫中包含的數(shù)據(jù)表和他們之間的相互關(guān)系如下圖1所示。
想要得到顧客的名字,這意味著必須要用到customers表,此外,我們不再需要構(gòu)造任何類型的條件——這里要獲取的是所有沒有任何限制的顧客,我們只是想知道他們第一次訂購的日期,查詢命令為:
SELECT c.LastName,
{SELECT MIN{OrderDate}
FROM Sales.SalesOrderHeader c
WHERE c.ContactID = c.ContactID}
AS? “Order Date”
FROM Person.Contact c
顯示結(jié)果如表1所示:
如果瀏覽所有的數(shù)據(jù),會看到可能在有一些行的OrderDate列中有NULL值,那是因為在SalesOrderHeader表中沒有與Customers表中(外部查詢)當前的記錄相匹配的記錄。
3 where 子句中的相關(guān)子查詢
在這里我們繼續(xù)用上邊的數(shù)據(jù)庫做實驗,想要查詢每一位顧客在系統(tǒng)中的第一張訂單的OrderID和OrderDate,根據(jù)查詢輸出要求,結(jié)果中要有OrderDate、OrderID以及CustomerID,這些信息都能在SalesOrderHeader中找到,想要知道每一位顧客在系統(tǒng)中的訂單日期,相關(guān)子查詢中,我們需要得到每一位顧客的最早的日期,解決這個查詢,可以通過兩個查詢來完成,第一個查詢中需要創(chuàng)建一個臨時表(臨時表中包CustomerID,MIN(OrderDate)兩個字段),在第二個查詢中聯(lián)接回該臨時表,如果要通過一個查詢來實現(xiàn),必須找到一個查找每個人的方法,該方法可以用內(nèi)部查詢來解決,該查詢基于外部查詢中當前的CustomerID執(zhí)行查找,然后需要把值返回給外部查詢,以便外部查詢能夠基于最早下訂單的日期來進行查找。SQL命令為:
SELECT o1.CustomerID,o1.SalesOrderID,o1.OrderDate FROM SalesOrderHeader o1
WHERE o1.OrderDate=(SELECT MIN(O2.OrderDate) FROM Sales.SalesOrderHeader o2 WHERE o2.CustomerID=O1.CustomerID) ORDER BY CustomerID
在代碼中,外部查詢看起來與嵌套子查詢非常類似,然而,內(nèi)部查詢對于外部查詢有一個明顯的引用。內(nèi)部查詢和外部查詢中都使用了別名,是因為當內(nèi)部查詢引用外部查詢中的列,或者外部查詢引用內(nèi)部查詢中的列時必須需要別名。
4 總結(jié)
相關(guān)子查詢,可以理解為2層循環(huán),要想執(zhí)行內(nèi)層的查詢,需要先從外層查詢到1個值出來。執(zhí)行的順序是,父查詢1個值,子查詢對這個得到的值進行1輪查詢,總查詢次數(shù)是m*n,在使用相關(guān)子查詢時,要合理的利用Select和Where在相關(guān)子查詢中的應用,另外相關(guān)子查詢將極大地降低數(shù)據(jù)檢索的速度,對于擁有幾百萬個行但沒有索引的大型表的非選擇性查詢更是如此,并盡可能地避免使用相關(guān)子查詢。
參考文獻:
[1]葛宇鋒. MongoDB查詢優(yōu)化技術(shù)研究[D].南京郵電大學,2017.
[2]毛思語,張利軍,張小芳,高錦濤,李戰(zhàn)懷.面向分布式數(shù)據(jù)庫的相關(guān)子查詢優(yōu)化策略[J].華東師范大學學報(自然科學版),2016(05):56-66.
[3]王千閣,何蒲,聶鐵錚,申德榮,于戈.區(qū)塊鏈系統(tǒng)的數(shù)據(jù)存儲與查詢技術(shù)綜述[J].計算機科學,2018,45(12):12-18.
[4]李斌,向軍文,李明建,羅群,胡博文,晉長昊.頁巖氣勘探中的空間關(guān)系型數(shù)據(jù)庫設計[J].非常規(guī)油氣,2019,6(02):111-116+90.
【通聯(lián)編輯:王力】