MySQL CTE (Common Table Expressions)示例全解析
CTE (Common Table Expression,公共表表達式) 是 MySQL 8.0 引入的重要特性,它允許在查詢中創(chuàng)建臨時命名結(jié)果集,提高復(fù)雜查詢的可讀性和可維護性。
基本語法
WITH cte_name AS ( SELECT ... -- CTE查詢定義 ) SELECT * FROM cte_name; -- 主查詢
CTE 主要特點
- 臨時結(jié)果集:只在查詢執(zhí)行期間存在
- 可引用性:可以在主查詢中多次引用
- 可讀性強:比嵌套子查詢更易理解
- 遞歸支持:支持遞歸查詢(MySQL 8.0+)
非遞歸 CTE
簡單 CTE 示例
WITH department_stats AS ( SELECT department_id, COUNT(*) as employee_count, AVG(salary) as avg_salary FROM employees GROUP BY department_id ) SELECT d.department_name, ds.employee_count, ds.avg_salary FROM departments d JOIN department_stats ds ON d.department_id = ds.department_id;
多 CTE 示例
WITH high_earners AS ( SELECT * FROM employees WHERE salary > 100000 ), it_employees AS ( SELECT * FROM employees WHERE department_id = 10 ) SELECT h.employee_id, h.name, 'High Earner' as category FROM high_earners h UNION ALL SELECT i.employee_id, i.name, 'IT Employee' as category FROM it_employees i;
遞歸 CTE
遞歸 CTE 可以處理層次結(jié)構(gòu)數(shù)據(jù),如組織結(jié)構(gòu)、評論樹等。
基本遞歸 CTE 結(jié)構(gòu)
WITH RECURSIVE cte_name AS ( -- 基礎(chǔ)部分(種子查詢) SELECT ... WHERE ... UNION [ALL] -- 遞歸部分 SELECT ... FROM cte_name JOIN ... WHERE ... ) SELECT * FROM cte_name;
遞歸 CTE 示例:組織結(jié)構(gòu)查詢
WITH RECURSIVE org_hierarchy AS ( -- 基礎(chǔ)部分:查找頂級管理者 SELECT employee_id, name, manager_id, 1 as level FROM employees WHERE manager_id IS NULL UNION ALL -- 遞歸部分:查找下屬員工 SELECT e.employee_id, e.name, e.manager_id, oh.level + 1 FROM employees e JOIN org_hierarchy oh ON e.manager_id = oh.employee_id ) SELECT * FROM org_hierarchy ORDER BY level, employee_id;
遞歸 CTE 示例:生成序列
WITH RECURSIVE number_sequence AS ( SELECT 1 AS n UNION ALL SELECT n + 1 FROM number_sequence WHERE n < 10 ) SELECT * FROM number_sequence;
CTE 的優(yōu)勢
- 提高可讀性:將復(fù)雜查詢分解為邏輯塊
- 避免重復(fù):可以多次引用同一個CTE
- 替代視圖:不需要創(chuàng)建永久視圖
- 遞歸能力:處理層次結(jié)構(gòu)數(shù)據(jù)
- 更好的優(yōu)化:MySQL優(yōu)化器能更好處理CTE
CTE 與派生表的比較
特性 | CTE | 派生表 |
---|---|---|
可讀性 | 高 | 低 |
可重用性 | 可在查詢中多次引用 | 每次使用都需要重新定義 |
遞歸支持 | 支持 | 不支持 |
性能 | 通常更好 | 可能較差 |
語法清晰度 | 更清晰 | 嵌套較深時難以理解 |
實際應(yīng)用場景
- 數(shù)據(jù)報表:構(gòu)建復(fù)雜報表的多步數(shù)據(jù)處理
WITH monthly_sales AS ( SELECT DATE_FORMAT(order_date, '%Y-%m') as month, SUM(amount) as total_sales FROM orders GROUP BY month ), growth_rate AS ( SELECT month, total_sales, LAG(total_sales) OVER (ORDER BY month) as prev_sales, (total_sales - LAG(total_sales) OVER (ORDER BY month)) / LAG(total_sales) OVER (ORDER BY month) * 100 as growth_pct FROM monthly_sales ) SELECT * FROM growth_rate;
- 數(shù)據(jù)清洗:多步數(shù)據(jù)轉(zhuǎn)換
WITH raw_data AS ( SELECT * FROM source_table WHERE quality_check = 1 ), cleaned_data AS ( SELECT id, TRIM(name) as name, CASE WHEN age < 0 THEN NULL ELSE age END as age FROM raw_data ) SELECT * FROM cleaned_data;
- 路徑查找:圖數(shù)據(jù)查詢
WITH RECURSIVE path_finder AS ( SELECT start_node as path, start_node, end_node, 1 as length FROM graph WHERE start_node = 'A' UNION ALL SELECT CONCAT(pf.path, '->', g.end_node), g.start_node, g.end_node, pf.length + 1 FROM graph g JOIN path_finder pf ON g.start_node = pf.end_node WHERE FIND_IN_SET(g.end_node, REPLACE(pf.path, '->', ',')) = 0 ) SELECT * FROM path_finder;
性能考慮
- 物化:MySQL可能會物化CTE結(jié)果
- 遞歸深度:默認遞歸深度限制為1000,可通過
cte_max_recursion_depth
參數(shù)調(diào)整
SET SESSION cte_max_recursion_depth = 2000;
- 優(yōu)化器提示:可以使用提示影響CTE處理
WITH cte_name AS ( SELECT /*+ MERGE() */ * FROM table_name ) SELECT * FROM cte_name;
限制
- MySQL 8.0 之前版本不支持CTE
- 某些復(fù)雜遞歸查詢可能有性能問題
- 在存儲過程和函數(shù)中使用有限制
CTE是MySQL中處理復(fù)雜查詢的強大工具,合理使用可以顯著提高SQL代碼的可讀性和維護性。
到此這篇關(guān)于MySQL CTE (Common Table Expressions) 詳解的文章就介紹到這了,更多相關(guān)mysql cte內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql重置root密碼的完整步驟(適用于5.7和8.0)
這篇文章主要介紹了mysql重置root密碼的完整步驟,文中描述了如何停止MySQL服務(wù)、以管理員身份打開命令行、替換配置文件路徑、修改密碼以及重新啟動MySQL服務(wù)的過程,需要的朋友可以參考下2025-01-01MySQL將時間戳轉(zhuǎn)換為年月日格式的實現(xiàn)
在我們的項目開發(fā)過程中,經(jīng)常需要將時間戳或日期時間字段轉(zhuǎn)換為特定的格式,本文主要介紹了MySQL將時間戳轉(zhuǎn)換為年月日格式的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-08-08MyBatis-Plus查詢不到數(shù)據(jù)但使用SQL可以查詢到數(shù)據(jù)的問題排查解決
在使用MyBatis-Plus時,有時會出現(xiàn)查詢不到數(shù)據(jù)的問題,而直接執(zhí)行SQL卻能查詢到數(shù)據(jù),本文將介紹如何排查和解決這一問題,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-09-09homeassistant數(shù)據(jù)存儲到mysql數(shù)據(jù)庫方式
這篇文章主要介紹了homeassistant數(shù)據(jù)存儲到mysql數(shù)據(jù)庫方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12mysql數(shù)據(jù)庫優(yōu)化總結(jié)(心得)
本篇文章是對mysql數(shù)據(jù)庫優(yōu)化進行了詳細的總結(jié)與介紹,需要的朋友參考下2013-06-06RedHat6.5/CentOS6.5安裝Mysql5.7.20的教程詳解
這篇文章主要介紹了RedHat6.5/CentOS6.5安裝Mysql5.7.20的教程詳解,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11