SQL中的Subquery & CTE & Temporary Table 區(qū)別深度對比分析
Subquery、CTE 和 Temporary Table 的深度對比
這三個技術(shù)都用于創(chuàng)建臨時數(shù)據(jù)集,但它們在實(shí)現(xiàn)方式、使用場景和性能特點(diǎn)上有顯著差異。讓我們用"數(shù)學(xué)演草紙"的比喻來深入分析:
1. 子查詢 (Subquery)
比喻:就像在解題過程中隨手在題目旁邊寫的草稿計(jì)算
特點(diǎn):
- 內(nèi)聯(lián)性:直接嵌套在SQL語句中(SELECT/FROM/WHERE等子句內(nèi))
- 一次性使用:定義后只能在該處使用一次
- 無命名:通常沒有顯式的名稱(除非是派生表)
- 作用域:僅在包含它的查詢中有效
示例:
SELECT user_id FROM orders WHERE amount > (SELECT AVG(amount) FROM orders); -- WHERE子句中的子查詢
適用場景:
- 簡單的單次使用計(jì)算
- 作為過濾條件或比較值
- 快速測試不需要復(fù)用的邏輯
2. 公共表表達(dá)式 (CTE, Common Table Expression)
比喻:專門拿出一張草稿紙寫中間步驟,可以隨時翻看
特點(diǎn):
- 顯式命名:使用
WITH cte_name AS
語法定義 - 可復(fù)用性:在同一個WITH子句中可定義多個CTE,且后面的CTE可以引用前面的
- 查詢級作用域:僅在緊隨其后的單個SQL語句中有效
- 可遞歸:支持遞歸查詢(處理層次結(jié)構(gòu)數(shù)據(jù))
示例:
-- 使用CTE和比較運(yùn)算符 >,先篩選出消費(fèi)總額超過1000的高價值用戶和最近30天活躍用戶,最終通過 INTERSECT 取兩者的交集,找出??既高消費(fèi)又活躍的核心用戶群體??。 WITH high_value_customers AS ( SELECT user_id FROM orders GROUP BY user_id HAVING SUM(amount) > 1000 ), #篩選訂單總額超過1000的用戶 active_customers AS ( SELECT user_id FROM logins WHERE login_date > CURRENT_DATE - 30 ) #篩選30天內(nèi)有登錄記錄的活躍用戶 SELECT * FROM high_value_customers INTERSECT SELECT * FROM active_customers;
適用場景:
- 復(fù)雜查詢的模塊化設(shè)計(jì)
- 需要多次引用同一結(jié)果集
- 遞歸查詢
- 提高復(fù)雜查詢的可讀性
3. 臨時表 (Temporary Table)
比喻:專門準(zhǔn)備一個筆記本記錄中間結(jié)果,可以反復(fù)翻閱和修改
特點(diǎn):
- 物理存儲:實(shí)際存儲在tempdb中(內(nèi)存或磁盤)
- 會話級作用域:創(chuàng)建后在整個會話期間可用,直到顯式刪除或會話結(jié)束
- 可索引:可以添加索引優(yōu)化性能
- 可修改:支持INSERT/UPDATE/DELETE操作
- 跨查詢使用:可以被同一會話的多個查詢使用
示例:
CREATE TEMPORARY TABLE temp_high_value AS SELECT user_id FROM orders GROUP BY user_id HAVING SUM(amount) > 1000; ALTER TABLE temp_high_value ADD INDEX (user_id); -- 可以添加索引 SELECT * FROM temp_high_value h JOIN users u ON h.user_id = u.id; DROP TEMPORARY TABLE IF EXISTS temp_high_value; -- 顯式清理
適用場景:
- 復(fù)雜的ETL流程
- 需要多次重用的中間結(jié)果
- 大型數(shù)據(jù)集處理(特別是需要索引優(yōu)化時)
- 跨多個SQL語句共享數(shù)據(jù)
三者的核心對比
特性 | 子查詢 (Subquery) | CTE | 臨時表 (Temporary Table) |
---|---|---|---|
存儲方式 | 邏輯存在,不物理存儲 | 邏輯存在,可能被優(yōu)化器物化 | 物理存儲在tempdb |
作用域 | 當(dāng)前子句 | 當(dāng)前語句 | 整個會話 |
生命周期 | 查詢執(zhí)行期間 | 查詢執(zhí)行期間 | 顯式刪除或會話結(jié)束 |
是否可復(fù)用 | 不可復(fù)用 | 同一WITH子句內(nèi)可引用 | 跨查詢復(fù)用 |
是否可修改 | 不可修改 | 不可修改 | 可INSERT/UPDATE/DELETE |
是否支持索引 | 不支持 | 不支持 | 支持 |
性能特點(diǎn) | 簡單查詢高效 | 中等復(fù)雜度查詢最優(yōu) | 復(fù)雜數(shù)據(jù)處理最優(yōu) |
語法復(fù)雜度 | 簡單 | 中等 | 較高 |
典型使用場景 | 簡單過濾/計(jì)算 | 復(fù)雜查詢模塊化 | 跨語句共享數(shù)據(jù)/大型處理 |
如何選擇?
- 簡單計(jì)算 → 子查詢
- 中等復(fù)雜度查詢 → CTE(提高可讀性)
- 需要多次引用/修改 → 臨時表
- 遞歸查詢 → CTE WITH RECURSIVE
- 會話級重用 → 臨時表
記?。弘S著SQL復(fù)雜度的增加,通常的開發(fā)路徑是:子查詢 → CTE → 臨時表。優(yōu)化器對三者的處理方式不同,在性能關(guān)鍵場景中需要測試驗(yàn)證。
到此這篇關(guān)于SQL中的Subquery & CTE & Temporary Table 區(qū)別深度對比分析的文章就介紹到這了,更多相關(guān)sql subquery、CTE 和 temporary table內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
order by newid() 各種數(shù)據(jù)庫隨機(jī)查詢的方法
order by newid() 各種數(shù)據(jù)庫隨機(jī)查詢的方法,需要的朋友可以參考一下2013-04-04跨服務(wù)器查詢導(dǎo)入數(shù)據(jù)的sql語句
此語句可用來將另一服務(wù)器中的數(shù)據(jù)插入到本數(shù)據(jù)庫中的某一表內(nèi)2009-10-10解析SQL Server聚焦移除(Bookmark Lookup、RID Lookup、Key Lookup)
本文主要講解索引性能優(yōu)化,著重對Bookmark Lookup、RID Lookup、Key Lookup三者進(jìn)行移除的實(shí)現(xiàn)進(jìn)行解析,以此來提高查詢性能。希望對大家有所幫助2016-12-12SQL 多條件查詢幾種實(shí)現(xiàn)方法詳細(xì)介紹
這篇文章主要介紹了SQL 多條件查詢兩種實(shí)現(xiàn)方法詳細(xì)介紹的相關(guān)資料,一種是排列結(jié)合,另一種是動態(tài)拼接SQL,需要的朋友可以參考下2016-12-12大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法(推薦)
最近遇到這樣的問題:導(dǎo)入csv 數(shù)據(jù),并對導(dǎo)入的數(shù)據(jù)增加一個新的列date datetime,下面通過本文給大家分享大容量csv快速內(nèi)導(dǎo)入sqlserver的解決方法,感興趣的朋友一起看看吧2017-07-07實(shí)用的銀行轉(zhuǎn)賬存儲過程和流水號生成存儲過程
本篇文章給大家分享銀行轉(zhuǎn)賬存儲過程和流水號生成存儲過程,感興趣的朋友一起看看吧2015-09-09sql拆分字符串實(shí)現(xiàn)一行變多行的實(shí)例代碼
本文主要介紹了sql拆分字符串實(shí)現(xiàn)一行變多行的實(shí)例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09