SQL系列(九)—— 子查詢(subQuery)


1.子查詢

前面的系列介紹的都是簡單的查詢場景,其中都只涉及到單張表的數據檢索。但是在日常是實際應用中,數據模型之間的關系都非常的復雜,數據的需求一般都是來源於多個數據模型之間的組合而成,即對應多張表的數據關聯。

對應以上場景,在SQL中一般有三種實現的方式:

  • 使用多個單條SQL,按邏輯步驟檢索,將其中的一條檢索結果作為下一條檢索的條件;
  • 使用子查詢,即將多個單挑SQL利用相應的邏輯關鍵字合並,子查詢是DBMS所支持;
  • 使用表聯結的方式,即join;

本章就簡單的回顧下SQL中的子查詢,從上面的總結中可以看出,子查詢其實利用模型之間的關系將單條SQL合並成一條復雜的SQL。那么如果要寫出這樣的復雜子查詢的SQL,首先需要梳理清楚需求中的數據模型之間的關系,根據需求的結果區分出查詢主體,查詢的關聯關系體,然后再分成單步驟的SQL,最后將其合並即可;

下面看個例子:

有三個實體,對應三張表:

  • 顧客表
  • 商品表
  • 訂單表

訂單中含有商品id,顧客id。現在需求:查詢購買商品x1的所有顧客。

  1. 分析:最終的結果是要查詢出顧客,所以查詢柱體是顧客,即外查詢是顧客。但是查詢顧客的條件是,購買了x1商品的顧客,所以需要查出購買了x1商品的顧客id,然后根據顧客id查詢顧客,所以子查詢是根據商品id x1查詢。

  2. 步驟:

  • 在表orders中查詢x1商品的顧客id: select cus_id from orders where mer_id = 'x1';

  • 根據上述的查詢結果作為條件,查詢顧客:select * from customers where cus_id = 'xxxx';

最后將根據需求結果和實體的關聯關系合並SQL:

select * from customers where customers.cus_id in (select cus_id from orders where mer_id = 'x1');

其實SQL中子查詢有兩種應用方式:

  • 第一種也就上面的最常使用到的場景,將子查詢的結果作為外查詢的條件,即子查詢屬於外查詢where子句的一部分
  • 第二種常用是將子查詢統計結果作為外查詢的列

比如需求:統計每個顧客購訂單數量。

  1. 分析:顧客仍然是主體,所以外查詢是查顧客表。但是執行的邏輯剛好和上述例子相反,上述是以商品id為條件查詢顧客。這里是查詢顧客以及其訂單數,但是訂單數的統計是從顧客這一維度出發,所以需要根據顧客查詢訂單數。

  2. 步驟:

  • 先查詢出所有顧客: select * from customers;
  • 再根據顧客去統計每個顧客的訂單數: select count(*) from orders where orders.cus_id = 'xxxxx';

最后組合SQL:

select cus_id, cus_name, (select count(*) from orders where orders.cus_id = customers.cus_id) from customers;

以上例子是子查詢的第二種用法。

2.總結

上述總結的子查詢的兩種方式:

  • 要么是根據子查詢的邏輯結果作為外查詢的查詢條件(子查詢在where子句中)
  • 要么是根據外查詢的結果作為子查詢的條件(子查詢在select子句中)

SQL中沒有限制子查詢的數量,但是一般實際應用中子查詢的不宜使用過多:

  • 使用子查詢必然會導致SQL更為復雜,SQL表述的語義較為難以理解,可閱讀性變差
  • 子查詢使用過多,會嚴重消耗性能
  • 子查詢不利於SQL的調試,問題的排查


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM