
- SQL 教程
- SQL - 首頁
- SQL - 概述
- SQL - RDBMS 概念
- SQL - 資料庫
- SQL - 語法
- SQL - 資料型別
- SQL - 運算子
- SQL - 表示式
- SQL 資料庫
- SQL - 建立資料庫
- SQL - 刪除資料庫
- SQL - 選擇資料庫
- SQL - 重新命名資料庫
- SQL - 顯示資料庫
- SQL - 備份資料庫
- SQL 表
- SQL - 建立表
- SQL - 顯示錶
- SQL - 重命名錶
- SQL - 截斷表
- SQL - 克隆表
- SQL - 臨時表
- SQL - 修改表
- SQL - 刪除表
- SQL - 刪除表資料
- SQL - 約束
- SQL 查詢
- SQL - 插入查詢
- SQL - 選擇查詢
- SQL - Select Into
- SQL - Insert Into Select
- SQL - 更新查詢
- SQL - 刪除查詢
- SQL - 排序結果
- SQL 檢視
- SQL - 建立檢視
- SQL - 更新檢視
- SQL - 刪除檢視
- SQL - 重新命名檢視
- SQL 運算子和子句
- SQL - Where 子句
- SQL - Top 子句
- SQL - Distinct 子句
- SQL - Order By 子句
- SQL - Group By 子句
- SQL - Having 子句
- SQL - AND & OR
- SQL - BOOLEAN (BIT) 運算子
- SQL - LIKE 運算子
- SQL - IN 運算子
- SQL - ANY, ALL 運算子
- SQL - EXISTS 運算子
- SQL - CASE
- SQL - NOT 運算子
- SQL - 不等於
- SQL - IS NULL
- SQL - IS NOT NULL
- SQL - NOT NULL
- SQL - BETWEEN 運算子
- SQL - UNION 運算子
- SQL - UNION vs UNION ALL
- SQL - INTERSECT 運算子
- SQL - EXCEPT 運算子
- SQL - 別名
- SQL 連線
- SQL - 使用連線
- SQL - 內連線
- SQL - 左連線
- SQL - 右連線
- SQL - 交叉連線
- SQL - 全連線
- SQL - 自連線
- SQL - 刪除連線
- SQL - 更新連線
- SQL - 左連線 vs 右連線
- SQL - Union vs Join
- SQL 鍵
- SQL - 唯一鍵
- SQL - 主鍵
- SQL - 外部索引鍵
- SQL - 組合鍵
- SQL - 備用鍵
- SQL 索引
- SQL - 索引
- SQL - 建立索引
- SQL - 刪除索引
- SQL - 顯示索引
- SQL - 唯一索引
- SQL - 叢集索引
- SQL - 非叢集索引
- 高階 SQL
- SQL - 萬用字元
- SQL - 註釋
- SQL - 注入
- SQL - 託管
- SQL - Min & Max
- SQL - 空值函式
- SQL - 檢查約束
- SQL - 預設約束
- SQL - 儲存過程
- SQL - NULL 值
- SQL - 事務
- SQL - 子查詢
- SQL - 處理重複項
- SQL - 使用序列
- SQL - 自動遞增
- SQL - 日期和時間
- SQL - 遊標
- SQL - 公共表表達式
- SQL - Group By vs Order By
- SQL - IN vs EXISTS
- SQL - 資料庫調優
- SQL 函式參考
- SQL - 日期函式
- SQL - 字串函式
- SQL - 聚合函式
- SQL - 數值函式
- SQL - 文字和影像函式
- SQL - 統計函式
- SQL - 邏輯函式
- SQL - 遊標函式
- SQL - JSON 函式
- SQL - 轉換函式
- SQL - 資料型別函式
- SQL 有用資源
- SQL - 問答
- SQL - 快速指南
- SQL - 有用函式
- SQL - 有用資源
- SQL - 討論
SQL - 公共表表達式 (CTE)
公共表表達式 (CTE) 可以透過使複雜查詢更易於閱讀和簡單來簡化複雜查詢的管理和編寫,就像資料庫檢視和派生表一樣。我們可以透過將複雜查詢分解成簡單的塊來重用或重寫查詢。
SQL 公共表表達式
MySQL 中的 WITH 子句用於指定公共表表達式。
SQL 中的公共表表達式 (CTE) 是一次性結果集,即它是一個僅在單個查詢執行期間存在的臨時表。它允許我們在該查詢中專門處理資料,例如在 SELECT、UPDATE、INSERT、DELETE、CREATE、VIEW 或 MERGE 語句中使用它。
CTE 是臨時的,因為它無法儲存在任何地方以供以後使用;一旦查詢執行完畢,它就會丟失。
MySQL WITH 子句
要指定公共表表達式,我們使用包含一個或多個以逗號分隔的子句的 WITH 子句。在每個子句中,我們可以提供一個產生結果集的子查詢,併為該子查詢分配一個名稱。
在 8.0 之前的 MySQL 版本中,您無法使用 WITH 子句。
語法
以下是使用 WITH 子句建立 CTE 的語法:
WITH CTE_NAME (column_name) AS (query) SELECT * FROM CTE_NAME;
其中,
- CTE_NAME − 它是在 CTE 中分配給 CTE 的名稱。
- column_name − 它是 CTE 的列名,這對於提高查詢的可讀性很有用。
- query − 它定義 CTE,它可以是任何有效的 SQL 查詢。
- 定義 CTE 後,您可以在同一會話中的後續查詢中引用它。
示例
假設我們在 MySQL 資料庫中使用 CREATE TABLE 語句建立了一個名為 CUSTOMERS 的表,如下所示:
CREATE TABLE CUSTOMERS ( ID INT NOT NULL, NAME VARCHAR (20) NOT NULL, AGE INT NOT NULL, ADDRESS CHAR (25), SALARY DECIMAL (18, 2), PRIMARY KEY (ID) );
現在,我們正在向上面建立的表中插入一些記錄:
INSERT INTO CUSTOMERS VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 ), (2, 'Khilan', 25, 'Delhi', 1500.00 ), (3, 'Kaushik', 23, 'Kota', 2000.00 ), (4, 'Chaitali', 25, 'Mumbai', 6500.00 ), (5, 'Hardik', 27, 'Bhopal', 8500.00 ), (6, 'Komal', 22, 'Hyderabad', 4500.00 ), (7, 'Muffy', 24, 'Indore', 10000.00 );
建立的表如下所示:
ID | 姓名 | 年齡 | 地址 | 工資 |
---|---|---|---|---|
1 | Ramesh | 32 | 艾哈邁達巴德 | 2000.00 |
2 | Khilan | 25 | 德里 | 1500.00 |
3 | Kaushik | 23 | 科塔 | 2000.00 |
4 | Chaitali | 25 | 孟買 | 6500.00 |
5 | Hardik | 27 | 博帕爾 | 8500.00 |
6 | Komal | 22 | 海德拉巴 | 4500.00 |
7 | Muffy | 24 | 因多爾 | 10000.00 |
在這裡,我們正在建立一個名為 CUSTOMER_AGE 的公共表表達式 (CTE),它選擇所有年齡為 23 的客戶。然後,我們從 CTE 中檢索這些客戶的 ID、姓名和年齡。
WITH CUSTOMER_AGE AS ( SELECT * FROM customers WHERE AGE = 23) SELECT ID, NAME, AGE FROM CUSTOMER_AGE;
輸出
以下是上述查詢的輸出:
ID | 姓名 | 年齡 |
---|---|---|
3 | Kaushik | 23 |
來自多個表的 CTE
我們還可以建立一個公共表表達式 (CTE),它透過在 CTE 的子查詢中使用 JOIN 操作來組合來自多個表的資料。為此,我們需要使用逗號運算子分隔每個 CTE 定義,有效地將它們合併到一個語句中。
語法
以下是多個公共表表達式 (CTE) 的基本語法:
WITH CTE_NAME1 (column_name) AS (query), CTE_NAME2 (column_name) AS (query) SELECT * FROM CTE_NAME1 UNION ALL SELECT * FROM CTE_NAME2;
我們可以將多個公共表表達式 (CTE) 與各種 SQL 操作一起使用,例如 UNION、UNION ALL、JOIN、INTERSECT 或 EXCEPT。
示例
在這裡,我們定義了兩個 CTE,即 'CUSTOMERS_IN_DELHI' 和 'CUSTOMERS_IN_MUMBAI',以根據他們在德里和孟買的地址來區分客戶。然後,我們使用 UNION ALL 運算子將來自這兩個 CTE 的結果組合到單個結果集中,檢索來自這兩個城市的客戶資訊。
WITH CUSTOMERS_IN_DELHI AS ( SELECT * FROM CUSTOMERS WHERE ADDRESS = 'Delhi'), CUSTOMERS_IN_MUMBAI AS ( SELECT * FROM CUSTOMERS WHERE ADDRESS = 'Mumbai') SELECT ID, NAME, ADDRESS FROM CUSTOMERS_IN_DELHI UNION ALL SELECT ID, NAME, ADDRESS FROM CUSTOMERS_IN_MUMBAI;
輸出
上述查詢的輸出如下所示:
ID | 姓名 | 地址 |
---|---|---|
2 | Khilan | 德里 |
4 | Chaitali | 孟買 |
遞迴 CTE
公共表表達式是一個查詢,它會反覆迴圈引用自己的結果,直到返回空結果。
遞迴查詢在其執行期間不斷迭代資料的一個子集,並以自引用方式定義自身。這種自引用機制允許它反覆處理和擴充套件其結果,直到滿足停止條件。
要使 CTE 成為遞迴的,它必須包含 UNION ALL 語句並提供查詢的第二個定義,該定義利用 CTE 本身。這允許 CTE 反覆引用其自身的結果,從而在查詢中建立遞迴行為。
示例
現在,我們使用一個名為 recursive_cust 的遞迴 CTE 來從上面建立的 'CUSTOMERS' 表中檢索資料。最初,我們選擇工資超過 3000 的客戶,然後使用 UNION ALL 運算子遞迴地將年齡超過 25 的客戶追加到結果集中:
WITH recursive_cust (ID, NAME, ADDRESS, AGE) AS ( SELECT ID, NAME, ADDRESS, AGE FROM CUSTOMERS WHERE SALARY > 3000 UNION ALL SELECT ID, NAME, ADDRESS, AGE FROM CUSTOMERS WHERE AGE > 25 ) SELECT * FROM recursive_cust;
輸出
執行上述查詢時,將遞迴顯示來自客戶表中年齡大於 25 或工資大於 3000 的所有資料,如下所示:
ID | 姓名 | 地址 | 年齡 |
---|---|---|---|
4 | Chaitali | 孟買 | 25 |
5 | Hardik | 博帕爾 | 27 |
6 | Komal | 海德拉巴 | 22 |
7 | Muffy | 因多爾 | 24 |
1 | Ramesh | 艾哈邁達巴德 | 32 |
5 | Hardik | 博帕爾 | 27 |
示例
在以下查詢中,我們使用一個名為 Numbers 的遞迴 CTE 來生成並顯示從 1 到 5 的數字。遞迴部分不斷將 1 新增到前一個值,直到達到 5,從而建立一個序列:
WITH RECURSIVE Numbers AS ( SELECT 1 AS N UNION ALL SELECT N + 1 FROM Numbers WHERE N < 5 ) SELECT n FROM Numbers;
輸出
執行上述查詢後,我們得到以下輸出:
N |
---|
1 |
2 |
3 |
4 |
5 |
CTE 的優勢
以下是 CTE 的優點:
CTE 使程式碼維護更容易。
它提高了程式碼的可讀性。
它提高了查詢的效能。
CTE 允許簡單地實現遞迴查詢。
CTE 的劣勢
以下是 CTE 的缺點:
CTE 只能被遞迴成員引用一次。
我們不能在儲存過程中使用表變數和 CTE 作為引數。
CTE 可以代替檢視使用,但 CTE 無法巢狀,而檢視可以。