天天看點

sql join 子查詢_SQL—你應該知道的子查詢

sql join 子查詢_SQL—你應該知道的子查詢

(本文結合《SQL基礎教程》整理)

文章結構

  • 視圖
  • 子查詢
  • 變量子查詢
  • 關聯子查詢
  • 如何用SQL解決業務問題
  • 常見函數
視圖 視圖的定義:

視圖究竟是什麼呢?如果用一句話概述的話,就是“從 SQL 的角度來看視圖就是一張表”。資料庫中的資料實際上會被儲存到計算機的儲存設備(通常是硬碟)中。是以,我們通過 SELECT 語句查詢資料時,實際上就是從儲存設備(硬碟)中讀取資料,進行各種計算之後,再将結果傳回給使用者這樣一個過程。但是使用視圖時并不會将資料儲存到儲存設備之中,而且也不會将資料儲存到其他任何地方。實際上視圖儲存的是 SELECT 語句。我們從視圖中讀取資料時,視圖會在内部執行該 SELECT 語句并建立出一張臨時表,臨時表會在用戶端和資料庫斷開連接配接的時候自動删除。

sql join 子查詢_SQL—你應該知道的子查詢

(以上文字和圖檔整理自:《SQL基礎教程》)

視圖的優點:

①由于視圖無需儲存資料,是以可以節省儲存設備的容量。

②第二個優點就是可以将頻繁使用的 SELECT 語句儲存成視圖,減少重複書寫。視圖建立好之後,隻需在 SELECT 語句中進行調用。在進行彙總以及複雜的查詢條件導緻 SELECT 語句非常龐大時,使用視圖可以大大提高效率。

③視圖中的資料會随着原表的變化自動更新,視圖就是封裝好的SELECT 語句,定義視圖時可以使用任何 SELECT 語句,既可以使用 WHERE、 GROUP BY、 HAVING,也可以通過 SELECT * 來指定全部列。

如何建立視圖:【也是在建立查詢中建立,然後重新整理即可】
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

視圖的外在表現形式是一張臨時表

注意:SELECT 語句需要書寫在 AS 【像,和...一樣】關鍵字之後。 SELECT 語句中列的排列順序和視圖中列的排列順序相同。

如何使用視圖:
sql join 子查詢_SQL—你應該知道的子查詢
如何删除視圖:
sql join 子查詢_SQL—你應該知道的子查詢
注意事項:

①在 FROM 子句中使用視圖的查詢,通常有如下兩個步驟:

sql join 子查詢_SQL—你應該知道的子查詢

通常來說,使用視圖的查詢通常需要執行 2 條以上的 SELECT 語句

②可以以視圖為基礎建立視圖的多重視圖,實際使用中,應該盡量避免在視圖的基礎上建立視圖。這是因為對多數 DBMS 來說,多重視圖會降低 SQL 的性能。

sql join 子查詢_SQL—你應該知道的子查詢

③定義視圖時不能使用ORDER BY子句。

④視圖和表需要同時進行更新,是以通過彙總得到的視圖無法進行更新(詳細原因見《SQL基礎教程》P156)。

子查詢

子查詢定義:子查詢就是将用來定義視圖的SELECT語句直接用于FROM子句當中,子查詢就是一次性視圖(SELECT語句)。是以與視圖不同,子查詢在SELECT語句執行完畢之後就會消失。

FROM子句之後的子查詢

案例1:要求根據商品種類(product_type)對資料進行彙總。

先回憶一下視圖的建立和使用的過程:

sql join 子查詢_SQL—你應該知道的子查詢

表product

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

建立的視圖

再來看看能夠實作同樣功能的

子查詢

的建立和使用的過程:

sql join 子查詢_SQL—你應該知道的子查詢

【非常重要:】from子句後,每個子查詢派生出來的表都需要有自己的别名,不然會報錯

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

案例2:找出商品總數量為3的商品品類名稱。

子查詢可以嵌套【但是不建議】:

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

我們嘗試解釋一下上述語句的含義:

①最内層的子查詢(ProductSum)與之前一樣,根據商品種類(product_type)對資料進行彙總。

②外層的子查詢将商品數量(cnt_product)限定為 3,結果就得到了 1 行廚房用具的資料,如下圖。

sql join 子查詢_SQL—你應該知道的子查詢
WHERE子句中的子查詢

案例3:哪些學生的成績比課程0002的全部成績裡的任意一個高?【ANY (子查詢)括号裡的資料以集合形式呈現】

sql join 子查詢_SQL—你應該知道的子查詢

案例4:哪些學生的成績比課程0002的全部成績裡都高?【all(子查詢)】

sql join 子查詢_SQL—你應該知道的子查詢

需要注意的是:子查詢隻是充當了視圖的功能并不會産生新的視圖,就像視圖僅僅建立了一張臨時表是一個道理。

标量子查詢

标量子查詢的定義:

标量就是單一的意思,标量子查詢就是

傳回單一值

的子查詢。

sql join 子查詢_SQL—你應該知道的子查詢
案例:

根據上表的資料結構考慮一個問題:查詢出銷售單價高于平均銷售單價的商品。

根據正常思維,幾乎會本能的在WHERE子句中使用聚集函數。

sql join 子查詢_SQL—你應該知道的子查詢

如下圖,我們發現SELECT 語句的查詢結果是單一的值(73266.6667)。是以,我們可以直接将這個結果用到之前失敗的查詢之中。

sql join 子查詢_SQL—你應該知道的子查詢

結合後的效果如下:

sql join 子查詢_SQL—你應該知道的子查詢

子查詢的結果是 73266.6667,是以會用該值替換子查詢的部分

需要注意的是:标量子查詢的書寫位置并不僅僅局限于 WHERE 子句中,

通常任何可以使用單一值的位置都可以使用【類似一個常數】

。也就是說,

能夠使用常數或者列名的地方

,無論是 SELECT 子句、GROUP BY 子句、 HAVING 子句,還是ORDER BY 子句,幾乎所有的地方都可以使用。

案例1:

将全部商品的單價加入原表格

我們将子查詢的語句放到了SELECT子句後】:

sql join 子查詢_SQL—你應該知道的子查詢

從上述結果可以看出,在商品一覽表中加入了全部商品的平均單價。有時我們會需要這樣的資料。

案例2

:選取出銷售均價高于全部商品的平均銷售單價的商品種類

我們将子查詢的語句放到了HAVING子句後】。

sql join 子查詢_SQL—你應該知道的子查詢
标量子查詢注意事項:

①标量子查詢絕對不能傳回多行結果。也就是說,如果子查詢傳回了多行結果,那麼它就不再是标量子查詢,而僅僅是一個普通的子查詢了。

sql join 子查詢_SQL—你應該知道的子查詢

關聯子查詢

1.關聯子查詢:關聯子查詢會在涉及分組後的組内再計算的場景。 2.問題引入

案例1:選取出各商品種類中高于該商品種類的平均銷售單價的商品。

'商品種類的平均銷售單價需要分組後再計算,需要用到關聯子查詢'

問題拆解:①找出每個商品種類的平均銷售單價。②将各自商品與自己對應的商品種類的平均銷售單價進行比較。

第一步:找出每個商品種類的平均銷售單價。

sql join 子查詢_SQL—你應該知道的子查詢

第二步:将各自商品與自己對應的商品種類的平均銷售單價進行比較。

sql join 子查詢_SQL—你應該知道的子查詢

如果我們使用前一節(标量子查詢)的方法,直接把上述SELECT 語句使用到 WHERE 子句當中的話,就會發生錯誤。出錯原因前一節已經講過了,該子查詢會傳回 3 行結果(1000、300、146000),并不是标量子查詢。

正确的做法是使用關聯子查詢:

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

其中紅色方框的運作邏輯是:

①執行到紅框部分時,先從父查詢的P1表中取出第一行值,并且傳遞到子查詢中,然後第一行記錄中取出product_type值'衣服'【p1.product_type】,于是紅框等式右邊的值替換為:'衣服',于是

子查詢語句

實際變成如下所示,并且将該次完整的子查詢結果傳回給外層的父查詢。

sql join 子查詢_SQL—你應該知道的子查詢

②将avg(sale_price)=1000作為傳回值,同時限定條件:product_type='衣服'【展現關聯】,傳回到父查詢中去,父查詢實際上成為:

sql join 子查詢_SQL—你應該知道的子查詢

③執行該次父查詢,我們發現,因為衣服隻有一個品類,商品種類的均值就是本身,是以查詢不到符合條件(大于1000且類型為衣服)。

④我們按上面相同的步驟,再從父查詢的P1表中取出第二行記錄傳入子查詢,得到第二行記錄中product_type的值為'辦公用品'【p1.product_type】,再重複上述幾步,我們發現'辦公用品'中的打孔器是符合篩選條件的,拆分的步驟大概如下。

sql join 子查詢_SQL—你應該知道的子查詢

⑤最後,循環以上步驟,将外部p1的每一行都傳遞到子查詢,子查詢依次讀取外部查詢傳遞來的每一行值,并将其用到子查詢上,直到外部查詢所有的行都處理完為止.然後傳回查詢最終查詢結果:

sql join 子查詢_SQL—你應該知道的子查詢

案例2:查詢每個商品的價格和它們

所處種類的平均價格

'所處種類的平均價格需要分組後在計算,需要關聯子查詢'
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

該關聯子查詢中,Group By對product_type進行分組其實沒有必要,因為上面where子句完成了實際上的分組功能

總結:①

關聯子查詢主要使用場景為:

分組後需要進行組内操作的場景,組内的操作會由關聯子查詢完成,

同組的類似工作,靠父查詢協調,遇到關聯子查詢的問題時,需要清晰明白各層查詢的具體功能。②關聯子查詢的執行原理:關聯子查詢會引用外部查詢中的

一列或多列

.在執行時,外部查詢的

每一行都被一次一行地

傳遞給子查詢.子查詢依次讀取外部查詢傳遞來的每一行值,子查詢為每一行資料執行一次并傳回它的記錄,直到父查詢所有的行都處理完為止,然後傳回查詢結果。

關聯子查詢和普通子查詢的差別:

①關聯子查詢的執行依賴于外部查詢的資料,外部查詢執行一行,子查詢就執行一次。此外,在關聯子查詢中是資訊流是雙向的。外部查詢的每行資料傳遞一個值給子查詢,

然後子查詢為每一行資料執行一次并傳回它的記錄

。然後,外部查詢根據傳回的記錄做出決策。

②非相關子查詢是獨立于外部查詢的子查詢,非相關子查詢是獨立于外部查詢的子查詢,子查詢總共執行一次,執行完畢後将值傳遞給外部查詢。

③關聯子查詢中: 1. 先執行外層查 2. 再執行内層查詢

④普通子查詢中: 1. 先執行内層查詢 2. 再執行外層查詢

如何用SQL解決業務問題

①翻譯成大白話

②寫出分析思路

③寫出對應的SQL子句

各種函數

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

日期函數:

sql join 子查詢_SQL—你應該知道的子查詢

Sqlzoo練習:

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

不知道為什麼出錯......

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

gdp>0,是為了排除NULL值,NULL不能使用比較運算符,因為NULL表示不确定,無法确定排序

那為什麼上面MAX()函數沒有出現問題呢?因為當列名作為參數傳入聚集函數的時候,那麼在計算之前就已經把NULL 排除在外了。是以,無論有多少個 NULL 都會被無視。但是如果是COUNT(*)這樣的形式,NULL會納入運算。

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

嘗試解析一下整個運作流程,加深對關聯子查詢的了解和記憶。

sql join 子查詢_SQL—你應該知道的子查詢

注意的ALL的靈活使用,若此處改成>=ALL,則可以選出每個州,排名最後的那個國家。

sql join 子查詢_SQL—你應該知道的子查詢

上圖中group by continent包不包含都無所謂

sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢
sql join 子查詢_SQL—你應該知道的子查詢

第十題中,子查詢引用了外部查詢的兩列【continent】【name】。

繼續閱讀