WHERE 子句中使用子查詢:深度解析與最佳實踐

🔍 WHERE 子句中使用子查詢:深度解析與最佳實踐

WHERE 子句中使用子查詢是 SQL 的高階技巧,可實現動態條件過濾。以下是全面指南,涵蓋語法、類型、陷阱及優化策略:


📜 一、基礎語法結構

SELECTFROM 主表 
WHERE 列 操作符 (SELECT 子查詢);

🧩 二、三種核心類型

1. 標量子查詢(單行單列)
-- 查詢工資高于平均工資的員工
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees  -- 返回單個值
);-- 可搭配比較運算符:=, >, <, >=, <=, <>
2. 行子查詢(單行多列)
-- 查找與特定員工職位+部門相同的員工
SELECT name, job, dept
FROM employees
WHERE (job, dept) = (SELECT job, dept FROM employees WHERE id = 101  -- 返回單行多列
);
3. 集合子查詢(多行單列)
-- 查詢有訂單的客戶
SELECT name 
FROM customers
WHERE id IN (SELECT DISTINCT cust_id FROM orders  -- 返回多行單列
);-- 常用操作符:IN, NOT IN, ANY, ALL, EXISTS

?? 三、六大關鍵注意事項

1. NULL 值的致命陷阱
-- ? 危險:NOT IN 遇 NULL 返回空結果
SELECT name 
FROM products
WHERE id NOT IN (SELECT product_id FROM discontinued  -- 若子查詢含 NULL
);-- ? 解決方案:顯式過濾 NULL
SELECT name 
FROM products
WHERE id NOT IN (SELECT product_id FROM discontinued WHERE product_id IS NOT NULL  -- 關鍵!
);
2. 子查詢返回結果數量
-- ? 錯誤:標量子查詢返回多行
SELECT name 
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees GROUP BY dept  -- 多行!
);-- ? 修正:確保返回單行
WHERE salary IN (SELECT ...)  -- 改用 IN
3. 性能黑洞(關聯子查詢)
-- ? 低效:每行執行一次子查詢(O(n2))
SELECT name, salary
FROM employees e
WHERE salary > (SELECT AVG(salary) FROM employees WHERE dept = e.dept  -- 關聯子查詢
);-- ? 優化:先聚合再連接
WITH dept_avg AS (SELECT dept, AVG(salary) avg_salFROM employees GROUP BY dept
)
SELECT e.name, e.salary
FROM employees e
JOIN dept_avg d ON e.dept = d.dept
WHERE e.salary > d.avg_sal;
4. 索引失效場景
-- ? 子查詢中對列使用函數
WHERE id IN (SELECT UPPER(product_code) FROM products  -- 索引失效!
)-- ? 優化:主查詢預處理
WHERE UPPER(id) IN (SELECT product_code FROM products)
5. EXISTS vs IN 的選擇
場景推薦原因
子查詢結果集小IN解析更快
子查詢結果集大EXISTS短路執行,不加載全部結果
需要處理 NULLEXISTS天然避免 NOT IN NULL 陷阱
關聯子查詢EXISTS通常更高效
-- EXISTS 示例(檢查存在訂單)
SELECT name
FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o   -- 不返回數據,只檢查存在性WHERE o.cust_id = c.id   -- 關聯條件
);
6. 同名字段歧義
-- ? 錯誤:主查詢與子查詢同名沖突
SELECT id, name
FROM employees
WHERE dept_id IN (SELECT id FROM depts WHERE name = 'IT'  -- 哪個 id?
);-- ? 方案:顯式別名限定
SELECT e.id, e.name
FROM employees e
WHERE e.dept_id IN (SELECT d.id FROM depts d WHERE d.name = 'IT'
);

🚀 四、性能優化策略

1. 子查詢轉為連接
-- 原始子查詢
SELECT * 
FROM products p
WHERE p.category_id IN (SELECT id FROM categories WHERE type = 'ELECTRONIC'
);-- ? 優化為 JOIN
SELECT p.*
FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.type = 'ELECTRONIC';
2. 限制子查詢返回列
-- ? 低效:返回所有列
WHERE id IN (SELECT * FROM ...)-- ? 高效:只返回必要列
WHERE id IN (SELECT id FROM ...)
3. 臨時表物化
-- 復雜子查詢先存為臨時表
CREATE TEMPORARY TABLE temp_ids AS
SELECT id FROM large_table WHERE condition;-- 主查詢使用臨時表
SELECT * 
FROM main_table 
WHERE id IN (SELECT id FROM temp_ids);

🔧 五、高級用法示例

1. 多層嵌套子查詢
-- 找出銷售額超過部門平均的產品
SELECT product_name
FROM sales s
WHERE amount > (SELECT AVG(amount)FROM sales WHERE dept_id = (SELECT dept_id FROM products WHERE id = s.product_id)
);
2. ANY/ALL 運算符
-- 工資高于IT部門任意員工的銷售
SELECT name 
FROM sales_emps
WHERE salary > ANY (SELECT salary FROM it_emps
);-- 工資高于IT部門所有員工
WHERE salary > ALL (SELECT ...)
3. 條件組合
-- 多條件子查詢
SELECT *
FROM orders
WHERE cust_id IN (SELECT id FROM vip_customers)AND product_id NOT IN (SELECT id FROM discontinued_products);

💎 終極使用指南

場景推薦方案替代方案
簡單值過濾標量子查詢變量/JOIN
檢查記錄是否存在EXISTSJOIN ... WHERE NULL
多值匹配IN + 非關聯子查詢JOIN
關聯條件過濾關聯子查詢先聚合再連接
復雜邏輯判斷CASE + 子查詢應用層處理

📌 黃金法則

  1. 優先用 EXISTS 替代 IN(尤其 NOT EXISTS vs NOT IN
  2. 子查詢中絕對避免 SELECT *
  3. 超過 3 層嵌套考慮重構為 CTE 或臨時表
  4. EXPLAIN 分析執行計劃,關注 DEPENDENT SUBQUERY 警告

性能警示標志

-- 執行計劃中出現 ↓ 表示性能風險
+----+--------------------+--------+------+...
| id | select_type        | table  | type |
+----+--------------------+--------+------+
| 1  | PRIMARY            | e      | ALL  |
| 2  | DEPENDENT SUBQUERY | dept   | ALL  |  -- 關聯子查詢全表掃!
+----+--------------------+--------+------+

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86824.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86824.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86824.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從0到1:不文明現象隨手拍小程序開發日記(一)

前期調研 不文明現象隨手拍小程序&#xff1a;在城市的快速發展進程中&#xff0c;不文明現象時有發生&#xff0c;為了有效解決這一問題&#xff0c;提升城市文明程度&#xff0c; 市民若發現不文明行為&#xff0c;如亂扔垃圾、隨地吐痰、破壞公共設施、違規停車等&#xff…

STM32F103之SPI軟件讀寫W25Q64

一、W25Q64簡介 1.1 簡介 W25Q64(Nor flash)、 24位地址&#xff0c;64Mbit/8MByte、是一種低成本、小型化、使用簡單的非易失性存儲器&#xff0c;常用于數據存儲、字庫存儲、固件程序存儲等場景 時鐘頻率&#xff1a;最大80MHz(STM32F103系統時鐘為72MHz…

vue3+element-plus 組件功能實現 上傳功能

一、整體功能概述 這段代碼實現了一個基于 Vue 3 和 Element Plus 組件庫的文件導入及預覽功能模塊。主要包含了一個主導入對話框&#xff08;用于上傳文件、展示文件相關信息、進行導入操作等&#xff09;以及一個用于預覽文件內容的預覽對話框。支持導入特定格式&#xff08;…

OpenCV中創建Mat對象

第1章 創建Mat對象 1.1. 創建空的 Mat 對象 cv::Mat mat; 1.2. 創建灰度圖像 // 創建一個 3 行 4 列、8位無符號單通道矩陣&#xff08;相當于灰度圖&#xff09; cv::Mat mat(3, 4, CV_8UC1); 1.3. 創建彩色圖像 // 創建三通道矩陣&#xff08;相當于彩色圖像&#xff0…

10、做中學 | 五年級下期 Golang循環控制

一、一個小需求 我想要打印10遍hello world,你想怎么編寫呢&#xff1f; // 需求&#xff1a;打印10遍"hello world"fmt.Println("hello world")fmt.Println("hello world")fmt.Println("hello world")fmt.Println("hello world…

機器學習算法-K近鄰算法-KNN

1. K近鄰算法是什么&#xff1f; 定義&#xff1a; K近鄰是一種基于實例的懶惰學習&#xff08;Lazy Learning&#xff09;算法&#xff0c;用于分類和回歸任務。 核心思想&#xff1a;“物以類聚”——通過計算樣本間的距離&#xff0c;找到目標點的最近K個鄰居&#xff0c;…

基于vue框架的法律知識咨詢普及系統gwuv7(程序+源碼+數據庫+調試部署+開發環境)帶論文文檔1萬字以上,文末可獲取,系統界面在最后面。

系統程序文件列表 項目功能&#xff1a;用戶,知識類型,律師,律師推薦,法律知識,新聞類型,法律新聞,咨詢律師 開題報告內容 基于Vue框架的法律知識咨詢普及系統開題報告 一、研究背景與意義 隨著法治社會建設的深入推進&#xff0c;公眾對法律知識的需求呈現爆發式增長。然而…

Netty 揭秘CompositeByteBuf:零拷貝優化核心技術

CompositeByteBuf 類 核心設計目標?? ??虛擬緩沖區??&#xff1a;將多個 ByteBuf 合并為單一邏輯視圖&#xff0c;減少數據復制。??零拷貝優化??&#xff1a;通過組合而非復制提升性能。??引用計數管理??&#xff1a;統一管理底層 ByteBuf 的生命周期。 核心成…

用css實現文字字體顏色漸變

用css實現文字字體顏色漸變 background-clip 是CSS3中新增的屬性&#xff0c;可以用于指定背景圖片或顏色的繪制范圍。利用 background-clip 屬性實現文字顏色從左到右、從綠到白的漸變效果&#xff1a; 代碼如下&#xff1a; .gradient-color {background-image: linear-gr…

SpringBatch處理數據性能優化

SpringBatch的Step默認使用同步方式批量處理數據&#xff0c;也可以通過配置將讀數改為同步&#xff0c;處理和寫入改為異步方式。 1、同步處理Step SpringBatch的Step一般由ItemReader、ItemProcessor和ItemWriter組成&#xff0c;其中ItemProcessor是可選的。他的設計思路的…

【機器學習深度學習】前饋神經網絡(單隱藏層)

目錄 一、什么是前饋神經網絡&#xff1f; 二、數學表達式是什么&#xff1f; 三、為什么需要“非線性函數”&#xff1f; 四、NumPy 實現前饋神經網絡代碼示例 五、 運行結果 六、代碼解析 6.1 初始化部分 6.2 前向傳播 6.3 計算損失&#xff08;Loss&#xff09; 6…

設計模式系列(08):創建型模式 - 原型模式

系列導讀&#xff1a;完成創建型模式的學習&#xff0c;我們來看最后一個創建型模式——原型模式。它通過復制已有對象來創建新對象&#xff0c;是一種獨特的創建方式。 解決什么問題&#xff1a;通過復制現有對象來創建新對象&#xff0c;而不是重新實例化。適用于對象創建成本…

區塊鏈到底是什么?

區塊鏈本質上是一種去中心化的分布式賬本技術&#xff0c;具有以下核心特點&#xff1a; - 去中心化&#xff1a;沒有中央管理機構&#xff0c;數據由網絡中的多個節點共同維護&#xff0c;比如比特幣網絡中各個節點都保存著完整賬本。 - 分布式存儲&#xff1a;數據不是存在一…

系統架構設計師論文分享-論ATAM的使用

我的軟考歷程 摘要 2023年2月&#xff0c;我司通過了研發紗線MES系統的立項&#xff0c;該系統為國內紗線工廠提供SAAS服務&#xff0c;旨在提高紗線工廠的數字化和智能化水平。我在本項目中擔任系統架構設計師&#xff0c;負責整個項目的架構設計工作。本文結合我在該項目中…

vue-28(服務器端渲染(SSR)簡介及其優勢)

服務器端渲染&#xff08;SSR&#xff09;簡介及其優勢 服務器端渲染&#xff08;SSR&#xff09;是現代網絡應用的關鍵技術&#xff0c;特別是使用 Vue.js 等框架構建的應用。它通過在服務器上渲染初始應用狀態來彌補傳統單頁應用&#xff08;SPA&#xff09;的局限性&#x…

工業電子 | 什么是SerDes,為何工業和汽車應用需要它?

重點內容速覽&#xff1a; 1. 什么是SerDes&#xff1f; 2. ADI&#xff1a;私有協議的GMSL將向公有協議轉變 3. TI&#xff1a;工業和汽車有兩套SerDes解決方案 4. Microchip&#xff1a;推出通用協議SerDes芯片 5. 羅姆&#xff1a;主要針對汽車領域 6. 國產SerDes芯…

大事件項目記錄4-用戶接口開發-更新用戶基本信息

4&#xff09;更新用戶基本信息。 UserController.java&#xff1a; UserMapper.java&#xff1a; Update("update user set nickname #{nickname},email #{email},update_time #{updateTime} where id #{id}")void update(User user); UserServiceInterface…

Transformer結構--輸入編碼(BPE,PE)

在Transformer結構中&#xff0c;輸入編碼是模型處理文本數據的關鍵步驟&#xff0c;其中**BPE&#xff08;Byte Pair Encoding&#xff0c;字節對編碼&#xff09;和PE&#xff08;Positional Encoding&#xff0c;位置編碼&#xff09;**是兩種重要的編碼方式&#xff0c;它們…

Confluence-測試用例設計指導方法

測試經驗知識庫 典型的測試場景驗證點各個項目有價值的經驗和測試點 測試經驗知識庫 - 草稿測試用例執行量化指導建議 何時需要進行全量測試和如何定義和執行測試用例量的一些建議和標準 端對端&#xff08;E2E&#xff09;測試用例設計指導方案 在測試行業中&#xff0c;端到端…

淺析JVM

一、JVM運行流程 如圖&#xff1a; JVM由四個部分構成&#xff1a; 1.類加載器 加載類文件到內存2.運行時數據區 寫的程序需要加載到這里才能運行3.執行引擎 負責解釋命令&#xff0c;提交操作系統執行4.本地接口 融合不同編程語言為java所用&#xff0c;如Java程序驅動打印…