子查詢 (SQL Subquery)
我們可以將一個 SQL 查詢語句塞入另一個 SQL 查詢語句中,這就是子查詢 (subquery)。子查詢是一個查詢內的查詢,我們可以用來連接資料表,或在不能使用單一語句來完成的查詢時我們就需要用到子查詢。
子查詢語法 (SQL Subquery Syntax)
SELECT column_name(s)
FROM table_name
WHERE column_name operator
(SELECT column_name FROM table_name WHERE condition);
子查詢用法 (Example)
假設我們有一個員工資料表 employees:
| Name | Department | Salary |
|---|---|---|
| 張一 | 業務部 | 35000 |
| 王二 | 資訊部 | 42000 |
| 李三 | 業務部 | 38000 |
| 趙四 | 資訊部 | 45000 |
查詢薪水高於平均薪水的員工:
SELECT Name, Salary
FROM employees
WHERE Salary > (SELECT AVG(Salary) FROM employees);
查詢結果如下:
| Name | Salary |
|---|---|
| 王二 | 42000 |
| 趙四 | 45000 |
使用 CTE 改寫子查詢 (Common Table Expression)
除了子查詢之外,SQL 還提供了 CTE(Common Table Expression,通用表示式)作為替代寫法。CTE 使用 WITH 關鍵字來定義一個暫時的命名結果集,讓查詢變得更易讀、更好維護。當子查詢變得複雜或需要重複使用時,CTE 是更好的選擇。
CTE 語法 (CTE Syntax)
WITH cte_name AS (
SELECT column_name(s)
FROM table_name
WHERE condition
)
SELECT column_name(s)
FROM cte_name;
WITH 關鍵字用來定義 CTE,cte_name 是我們給這個暫時結果集的名稱,括號內的查詢就是 CTE 的定義。定義完成後,我們就可以在主查詢中像使用資料表一樣來使用 CTE。
CTE 用法範例 (CTE Example)
我們可以用 CTE 來改寫前面的子查詢範例,查詢薪水高於平均薪水的員工:
WITH avg_salary AS (
SELECT AVG(Salary) AS AvgSalary
FROM employees
)
SELECT Name, Salary
FROM employees, avg_salary
WHERE Salary > avg_salary.AvgSalary;
這個查詢與子查詢的結果完全相同,但 CTE 的寫法讓查詢的邏輯更清晰:先計算平均薪水,再用這個結果來篩選員工。
多個 CTE 的使用 (Multiple CTEs)
CTE 還有一個強大的優點,就是可以在同一個查詢中定義多個 CTE,用逗號分隔:
WITH dept_avg AS (
SELECT Department, AVG(Salary) AS AvgSalary
FROM employees
GROUP BY Department
),
overall_avg AS (
SELECT AVG(Salary) AS OverallAvg
FROM employees
)
SELECT d.Department, d.AvgSalary, o.OverallAvg
FROM dept_avg d, overall_avg o;
這個範例同時計算了各部門的平均薪水和全體平均薪水,如果用子查詢寫會變得難以閱讀,但用 CTE 就能清楰地分步驟處理。
子查詢與 CTE 的比較
| 比較項目 | 子查詢 (Subquery) | CTE (WITH) |
|---|---|---|
| 可讀性 | 巢狀結構,複雜時較難閱讀 | 分步定義,邏輯清晰 |
| 重複使用 | 需要重複寫同一段查詢 | 定義一次即可多次引用 |
| 遞迴查詢 | 不支援 | 支援遞迴 CTE |
| 適用場景 | 簡單的單次查詢 | 複雜的多步驟查詢 |
延伸閱讀
- SQL EXISTS
- SQL CASE
- SQL 聚合函數
- SQL 教學
- SQL SELECT
- SQL WHERE
- SQL JOIN
- SQL IN
- SQL UNION
- SQL INTERSECT
- SQL MINUS
留言功能已關閉。