示例 SQL 及執行順序分析(帶詳細注釋)
示例 1:基礎查詢(含多表關聯、過濾、分組、排序)
SELECT -- 1. 選擇字段(包含聚合函數和別名)e.department, COUNT(e.employee_id) AS total_employees, -- 聚合函數AVG(e.salary) AS avg_salary, MAX(e.salary) AS max_salary
FROM employees e
JOIN departments d ON e.department_id = d.department_id -- 2. 表關聯(JOIN)
WHERE e.hire_date >= '2020-01-01' -- 3. 行級過濾(WHERE)
GROUP BY e.department -- 4. 分組(GROUP BY)
HAVING AVG(e.salary) > 5000 -- 5. 分組后過濾(HAVING)
ORDER BY avg_salary DESC -- 6. 排序(ORDER BY)
LIMIT 10; -- 7. 限制結果(LIMIT)
示例 2:窗口函數與子查詢
SELECT -- 1. 選擇字段(包含窗口函數)e.*, SUM(e.salary) OVER (PARTITION BY department) AS dept_total_salary, -- 窗口函數(SUM OVER)RANK() OVER (ORDER BY salary DESC) AS salary_rank -- 排名函數(RANK OVER)
FROM (-- 子查詢(先執行)SELECT * FROM employees WHERE age BETWEEN 25 AND 35 -- 子查詢過濾
) e
WHERE e.department = 'Tech' -- 2. 外層過濾(WHERE)
ORDER BY salary_rank -- 3. 排序(ORDER BY)
LIMIT 5; -- 4. 限制結果(LIMIT)
示例 3:多表關聯 + UNION + DISTINCT
SELECT -- 第一個 SELECT 分支o.order_id, c.customer_name, o.total_amount, COUNT(DISTINCT oi.product_id) AS products_count
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
LEFT JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-12-31' -- 過濾訂單日期
GROUP BY o.order_id, c.customer_name, o.total_amount
HAVING products_count > 2 -- 分組后過濾
UNION -- 合并結果集
SELECT -- 第二個 SELECT 分支(不同結構)'Summary' AS order_id, 'Total Customers' AS customer_name, COUNT(DISTINCT c.customer_id) AS total_customers, NULL AS products_count
FROM customers c
WHERE c.registration_date >= '2023-01-01'
ORDER BY total_amount DESC -- 全局排序
LIMIT 5; -- 限制最終結果
執行順序與邏輯關系
SQL 執行流程(通用順序)
- FROM/JON:處理表關聯(如
JOIN
)和子查詢。 - WHERE:過濾行級條件。
- GROUP BY:按字段分組。
- HAVING:過濾分組后的結果。
- WINDOW FUNCTION:計算窗口函數(依賴分組后的數據)。
- SELECT:選擇字段并計算表達式(如聚合函數、別名)。
- DISTINCT:去重(若存在)。
- ORDER BY:排序結果。
- LIMIT/OFFSET:限制返回行數。
關鍵子句間的邏輯關系
子句 | 依賴關系 | 輸出結果 |
---|---|---|
FROM | 無 | 基礎表或子查詢的原始數據 |
WHERE | 依賴 FROM 的結果 | 過濾后的行數據 |
GROUP BY | 依賴 WHERE 的結果 | 按字段分組后的數據集 |
HAVING | 依賴 GROUP BY 的結果 | 過濾分組后的組 |
WINDOW FUNCTION | 依賴 GROUP BY 和 HAVING 的結果(若存在) | 添加窗口函數計算的列 |
SELECT | 依賴所有前置子句的結果 | 最終輸出的字段(含聚合函數、別名、窗口函數結果) |
ORDER BY | 依賴 SELECT 的結果 | 排序后的結果集 |
LIMIT/OFFSET | 依賴 ORDER BY 的結果(若存在) | 最終返回的有限行數 |
表格總結:各 SQL 的關鍵字段與執行順序
SQL 示例 | 關鍵子句 | 執行順序 | 注釋要點 |
---|---|---|---|
示例 1 | SELECT , FROM , JOIN , WHERE , GROUP BY , HAVING , ORDER BY , LIMIT | 1. JOIN → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT → 6. ORDER BY → 7. LIMIT | - JOIN 先于 WHERE 執行- GROUP BY 必須包含非聚合字段 department - HAVING 過濾分組后的平均工資 |
示例 2 | SELECT (窗口函數), FROM (子查詢), WHERE , ORDER BY , LIMIT | 1. 子查詢 → 2. WHERE → 3. 窗口函數 → 4. SELECT → 5. ORDER BY → 6. LIMIT | - 子查詢先執行過濾年齡 - 窗口函數依賴分組后的數據(隱式分組) - RANK() 為全局排名 |
示例 3 | SELECT , FROM (多表 JOIN), WHERE , GROUP BY , HAVING , UNION , ORDER BY , LIMIT | 1. JOIN → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. UNION → 6. SELECT → 7. ORDER BY → 8. LIMIT | - UNION 合并兩個不同結構的 SELECT 結果- DISTINCT 去重產品 ID- 最終排序全局生效 |
關鍵點說明
-
窗口函數的特殊性:
- 示例 2 中的
SUM(...) OVER (PARTITION BY ...)
在GROUP BY
之后執行,允許對分組后的數據進行計算,但不會合并行。 - 窗口函數可與非聚合字段(如
e.*
)同時出現在SELECT
中。
- 示例 2 中的
-
子查詢的優先級:
- 示例 2 的內層子查詢(
SELECT * FROM employees WHERE age BETWEEN 25 AND 35
)在外部查詢的FROM
階段優先執行。
- 示例 2 的內層子查詢(
-
DISTINCT
的位置:- 示例 3 中的
COUNT(DISTINCT product_id)
在GROUP BY
階段計算,確保統計唯一產品數量。
- 示例 3 中的
-
UNION
的處理:- 示例 3 的
UNION
合并兩個 SELECT 結果后,才會執行全局的ORDER BY
和LIMIT
。
- 示例 3 的
通過以上分析,可清晰理解 SQL 各子句的執行順序及相互依賴關系,幫助優化查詢性能和結果準確性。