目錄
子查詢的相關概念:
子查詢的分類:
角度1:
單行子查詢:
單行比較操作符:
子查詢的空值情況:
多行子查詢:
多行比較操作符:
ANY和ALL的區別:
子查詢為空值的情況:
角度2:
相關(或者關聯)子查詢:
非相關(或者非關聯)子查詢:
EXISTS和NOT EXISTS關鍵字:
EXISTS:
NOT EXISTS:
子查詢的基本使用:
子查詢作為計算字段:
子查詢結果作為臨時表:
子查詢結果作為過濾條件:
舉例:
結論:
子查詢的相關概念:
子查詢是指一個查詢語句嵌套在另一個查詢語句的內部的查詢。SQL中子查詢的使用大大增加了SELECT查詢的能力,因為很多時候查詢需要從結果集中獲取數據,或者需要從同一個表中先計算得出一個數據結果,然后這個數據結果(可能是某一標量,也可能是某個集合)進行比較。
子查詢的稱謂規范:外查詢(主查詢)、內查詢(子查詢)。
子查詢需要使用()包裹,可多層嵌套。通常先執行子查詢,再將結果傳遞給外部查詢。
子查詢放在比較條件的右側,提高可讀性。
子查詢的分類:
角度1:
按照內查詢的結果返回一條還是多條記錄,將子查詢分為:
單行子查詢:
返回一個結果給主查詢進行使用。
單行比較操作符:
操作符 | 含義 |
= | 等于查詢的數據 |
> | 大于查詢的數據 |
>= | 大于等于查詢的數據 |
小于等于查詢的數據 | |
<> | 不等于查詢的數據 |
子查詢的空值情況:
子查詢如果查詢的結果為NULL,是不會進行報錯的。外查詢運用這個查詢結果也是NULL值。
多行子查詢:
返回多個結果給主查詢進行使用。
多行比較操作符:
操作符 | 含義 |
IN | 等于列表中任意一個 |
ANY | 需要和單行比較操作符一起使用,和子查詢返回的某一個值進行比較 |
ALL | 需要和單行比較操作符一起使用,和子查詢返回的所有值進行比較 |
SOME | 實際上是ANY的別名,作用相同,一般常用ANY |
ANY和ALL的區別:
?ANY:如果主查詢中的值滿足與子查詢返回的任意一個值之間的比較條件,則條件為真。
ALL:如果主查詢中的值滿足與子查詢返回的所有值之間的比較條件,則條件為真。
子查詢為空值的情況:
內查詢有一個NULL值的話,外查詢的結果為NULL。
角度2:
按照內查詢是否被多次執行,將子查詢分為:
相關(或者關聯)子查詢:
子查詢依賴外部查詢的當前行數據,需結合外部查詢逐步處理。
子查詢需要執行多次,即采用循環的方式,先從外部查詢開始,每次都傳入子查詢進行查詢,然后將結果反饋給外部。
非相關(或者非關聯)子查詢:
子查詢獨立于外部查詢執行,不引用外部查詢的任何字段,可單獨運行并返回固定結果集供外部查詢使用。
子查詢從數據表中查詢了數據結果,如果這個數據結果只執行一次,然后這個數據結果作為主查詢的條件進行執行。
EXISTS和NOT EXISTS關鍵字:
關聯子查詢通常會和EXISTS和NOT EXISTS關鍵字一起使用,用于檢查子查詢是否存在滿足條件的行。
EXISTS和NOT EXISTS基于布爾邏輯判斷數據的存在性而返回具體數據值。
EXISTS:
檢查子查詢是否返回至少一行記錄。
SELECT ...
FROM 主表
WHERE EXISTS (子查詢);
如果子查詢中不存在滿足條件的行:條件返回FALSE,繼續在子查詢中查找。
如果在子查詢中存在滿足條件的行:不在子查詢中繼續查找,條件返回TREU。
NOT EXISTS:
檢查子查詢是否沒有返回任何記錄。
如果子查詢中無結果:返回TRUE,保留改行。
如果子查詢中有結果:返回FALSE,丟棄該行。
SELECT ...
FROM 主表
WHERE NOT EXISTS (子查詢);
子查詢的基本使用:
子查詢作為計算字段:
必須返回單值。
SELECT 字段名1,字段名2,...
FROM 表名
WHERE 字段名3 比較操作符 (SELECT 返回的字段名FROM 表名WHERE 條件(不含聚合函數條件)
);
SELECT 字段名1,(SELECT 返回的字段名FROM 表名WHERE 條件
)
FROM 表名
WHERE 條件;
子查詢結果作為臨時表:
必須指定別名。
SELECT 字段名1,字段名2,...
FROM 表名1 JOIN (SELECT 字段名FROM 表名WHERE 條件
) AS 別名
WHERE 條件;
子查詢結果作為過濾條件:
SELECT 字段名1,字段名2,...
FROM 表名
WHERE 字段名 比較操作符 (SELECT 字段名,(聚合函數)FROM 表名[WHERE 條件(無聚合函數條件)]GROUP BY 非聚合函數字段名HAVING 條件(包含聚合函數條件)
);
舉例:
牛客網SQL題目:
返回購買價格為 10 美元或以上產品的顧客列表_牛客題霸_牛客網
OrderItems表示訂單商品表,含有字段訂單號:order_num、訂單價格:item_price;Orders表代表訂單信息表,含有顧客id:cust_id和訂單號:order_num
OrderItems表
order_num | item_price |
a1 | 10 |
a2 | 1 |
a2 | 1 |
a4 | 2 |
a5 | 5 |
a2 | 1 |
a7 | 7 |
Orders表
order_num | cust_id |
a1 | cust10 |
a2 | cust1 |
a2 | cust1 |
a4 | cust2 |
a5 | cust5 |
a2 | cust1 |
a7 | cust7 |
使用子查詢,返回單個訂單的購買價格為 10 美元或以上產品的顧客列表,結果無需排序。
【示例結果】返回顧客id cust_id
cust_id |
cust10 |
因為這里子查詢返回的結果為多個,所以使用多行比較操作符IN。?
SELECT Orders.cust_id
FROM Orders
WHERE Orders.order_num IN (SELECT OrderItems.order_numFROM OrderItemsWHERE OrderItems.item_price >=10
);
牛客網SQL題目:
確定哪些訂單購買了 prod_id 為 BR01 的產品(一_牛客題霸_牛客網
表OrderItems代表訂單商品信息表,prod_id為產品id;Orders表代表訂單表有cust_id代表顧客id和訂單日期order_date
OrderItems表
prod_id | order_num |
BR01 | a0001 |
BR01 | a0002 |
BR02 | a0003 |
BR02 | a0013 |
Orders表
order_num | cust_id | order_date |
a0001 | cust10 | 2022-01-01 00:00:00 |
a0002 | cust1 | 2022-01-01 00:01:00 |
a0003 | cust1 | 2022-01-02 00:00:00 |
a0013 | cust2 | 2022-01-01 00:20:00 |
編寫 SQL 語句,使用子查詢來確定哪些訂單(在 OrderItems 中)購買了 prod_id 為 "BR01" 的產品,然后從 Orders 表中返回每個產品對應的顧客 ID(cust_id)和訂單日期(order_date),按訂購日期對結果進行升序排序。
【示例結果】返回顧客id cust_id和定單日期order_date。
cust_id | order_date |
cust10 | 2022-01-01 00:00:00 |
cust1 | 2022-01-01 00:01:00 |
SELECT Orders.cust_id,Orders.order_date
FROM Orders
WHERE Orders.order_num IN (SELECT OrderItems.order_numFROM OrderItemsWHERE OrderItems.prod_id = 'BR01'
)
ORDER BY Orders.order_date ASC;
牛客網SQL題目:
返回購買 prod_id 為 BR01 的產品的所有顧客的電_牛客題霸_牛客網
你想知道訂購 BR01 產品的日期,有表OrderItems代表訂單商品信息表,prod_id為產品id;Orders表代表訂單表有cust_id代表顧客id和訂單日期order_date;Customers表含有cust_email 顧客郵件和cust_id顧客id
OrderItems表
Orders表
Customers表代表顧客信息,cust_id為顧客id,cust_email為顧客email
返回購買 prod_id 為BR01 的產品的所有顧客的電子郵件(Customers 表中的 cust_email),結果無需排序。
提示:這涉及 SELECT 語句,最內層的從 OrderItems 表返回 order_num,中間的從 Customers 表返回 cust_id。
【示例結果】
返回顧客email cust_email
我們先通過Orders表格中的order_num和OrderItems表格中的order_num進行相關的連接,查詢得到想要的prod_id為"BR01"的order_num值。然后再將結果反饋給Customers表來進行相關的查詢。因為這里主要講的是子查詢,所以就使用的子查詢嵌套來表示。
SELECT Customers.cust_email
FROM Customers
WHERE Customers.cust_id IN (SELECT Orders.cust_idFROM OrdersWHERE Orders.order_num IN (SELECT OrderItems.order_numFROM OrderItemsWHERE OrderItems.prod_id = 'BR01')
);
?牛客網SQL題目:
從 Products 表中檢索所有的產品名稱以及對應的銷售總_牛客題霸_牛客網
Products 表中檢索所有的產品名稱:prod_name、產品id:prod_id
prod_id | prod_name |
a0001 | egg |
a0002 | sockets |
a0013 | coffee |
a0003 | cola |
OrderItems代表訂單商品表,訂單產品:prod_id、售出數量:quantity
prod_id | quantity |
a0001 | 105 |
a0002 | 1100 |
a0002 | 200 |
a0013 | 1121 |
a0003 | 10 |
a0003 | 19 |
a0003 | 5 |
編寫 SQL 語句,從 Products 表中檢索所有的產品名稱(prod_name),以及名為 quant_sold 的計算列,其中包含所售產品的總數(在 OrderItems 表上使用子查詢和 SUM(quantity)檢索)。
【示例結果】返回產品名稱prod_name和產品售出數量總和
prod_name | quant_sold |
egg | 105 |
sockets | 1300 |
coffee | 1121 |
cola | 34 |
?這里將子查詢的結果作為一個臨時表,必須需要對臨時表進行起別名。先通過將Products表格和自身建立連接,得到想要的子查詢結果集,然后再將OrderItems表格建立連接。即可得到想要的結果集。
SELECT Products.prod_name,NewOrderItems.quant_sold
FROM Products JOIN (SELECT OrderItems.prod_id,SUM(OrderItems.quantity) AS quant_soldFROM OrderItemsGROUP BY OrderItems.prod_id
) AS NewOrderItems
ON Products.prod_id = NewOrderItems.prod_id;
牛客網SQL題目:?
返回每個顧客不同訂單的總金額_牛客題霸_牛客網
我們需要一個顧客 ID 列表,其中包含他們已訂購的總金額。
OrderItems表代表訂單信息,OrderItems表有訂單號:order_num和商品售出價格:item_price、商品數量:quantity。
Orders表訂單號:order_num、顧客id:cust_id
編寫 SQL語句,返回顧客 ID(Orders 表中的 cust_id),并使用子查詢返回total_ordered 以便返回每個顧客的訂單總金額,將結果按金額從大到小排序。
【示例結果】返回顧客id cust_id和total_order下單總額
因為要查詢顧客ID所對應的訂單總金額,所以通過OrderItems表格的自連接得到一個按照order_num分組并計算所對應的價格總和的臨時表。通過Orders表格和OrderItems表格進行連接查詢,得到想要的查詢結果集。
SELECT的執行順序:FROM在SELECT之前,并且子查詢先執行,所以能夠直接把NewOrderItems.total_ordered直接放在主查詢SELECT后面。
因為子查詢中含有聚合函數,所以子查詢中的過濾條件應該使用HAVING關鍵字。
SELECT Orders.cust_id,NewOrderItems.total_ordered
FROM Orders JOIN (SELECT OrderItems.order_num,SUM(OrderItems.item_price*OrderItems.quantity) AS total_orderedFROM OrderItemsGROUP BY OrderItems.order_numORDER BY total_ordered DESC
) AS NewOrderItems
ON Orders.order_num = NewOrderItems.order_num;
結論:
?在SELECT中,除了在GROUP BY和LIMIT之外,都能使用子查詢。