CTE 是一個「暫存」且「具名」的結果集合。
-- 定義 CTE 的 名稱 和 欄位
WITH sampleCTE (id, name, phoneNumber, age)
AS
-- 定義 CTE 的 Query
(
SELECT
id,
name,
phoneNumber,
date_part('year', NOW()) - date_part('year', dob) AS age
FROM member
WHERE phoneNumber IS NOT NULL
)
-- 使用 CTE
SELECT *
FROM sampleCTE
WHERE age >= 18
CTE 會暫時儲存 AS 括號中的 Query 結果,
用在同一個執行中 SELECT 、 INSERT 、 UPDATE 、 DELETE,
或是 CREATE VIEW 的 SELECT 上。
也可以在定義 CTE 的 Query 中使用,今天介紹的遞迴就是一個例子。
定義遞迴查詢 CTE 的概念大致上是:
假設資料為某家族的族譜,查詢目標為取得 Grandpa 的所有子孫
| Id | Name | ChildName |
| 1 | Grandpa | Dad |
| 2 | Grandpa | Uncle |
| 3 | Grandpa | Aunt |
| 4 | Dad | Me |
| 5 | Dad | Sister |
| 6 | Uncle | Cousin |
| 7 | Me | Daughter |
| 8 | Sister | Nephew |
| 9 | Daughter | Grandson |
| Name | ChildName | ChildLevel |
| Grandpa | Dad | 1 |
| Grandpa | Uncle | 1 |
| Grandpa | Aunt | 1 |
| Grandpa | Me | 2 |
| Grandpa | Sister | 2 |
| Grandpa | Cousin | 2 |
| Grandpa | Daughter | 3 |
| Grandpa | Nephew | 3 |
| Grandpa | Grandson | 4 |
使用 MSSQL 的話需要注意: 遞迴的部分必須使用 UNION ALL
WITH ChildrenCTE(Name, ChildName, ChildLevel) AS
(
-- 取得所有資料 (每個人的孩子) 作為第一層
SELECT Name, ChildName, 1 AS ChildLevel
FROM FamilyTree
UNION ALL
-- 遞迴取得每個人的子孫(不含孩子)
-- CTE 的查詢結果: 選取孫子(孩子的孩子)
SELECT FT.Name, Children.ChildName, Children.ChildLevel + 1
FROM FamilyTree AS FT
-- 使用 CTE 查詢: 父母名稱為資料中孩子名稱的資料
INNER JOIN ChildrenCTE AS Children
ON FT.ChildName = Children.Name
)
SELECT *
FROM ChildrenCTE
WHERE Name = 'Grandpa'
ORDER BY ChildLevel
跟 MSSQL 的做法差不多,只是要在 CTE 的名字前面加上 RECURSIVE。
且可以只使用 UNION , 不一定要 UNION ALL。
WITH RECURSIVE ChildrenCTE(Name, ChildName, ChildLevel) AS
(
-- 取得所有資料 (每個人的孩子) 作為第一層
SELECT Name, ChildName, 1 AS ChildLevel
FROM FamilyTree
UNION
-- 遞迴取得每個人的子孫(不含孩子)
-- CTE 的查詢結果: 選取孫子(孩子的孩子)
SELECT FT.Name, Children.ChildName, Children.ChildLevel + 1
FROM FamilyTree AS FT
-- 使用 CTE 查詢: 父母名稱為資料中孩子名稱的資料
INNER JOIN ChildrenCTE AS Children
ON FT.ChildName = Children.Name
)
SELECT *
FROM ChildrenCTE
WHERE Name = 'Grandpa'
ORDER BY ChildLevel
When you subscribe to the blog, we will send you an e-mail when there are new updates on the site so you wouldn't miss them.
評論