理解子句執行順序 (FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY) 是撰寫正確、高效查詢的前提。本文深度解析四大核心子句語法、常見錯誤與優化模式。
FROM table_source [ ,...n ]
table_source ::=
table_name [ [AS] alias ] [ ]
| view_name [ [AS] alias ]
| ( SELECT ... ) [AS] alias [ ( column_alias [ ,...n ] ) ] -- 衍生表
| function_name ( ... ) [AS] alias -- 表值函數
| table_source join_type table_source ON -- 連接
| table_source CROSS APPLY / OUTER APPLY table_value_func -- 交叉應用
FROM Orders o JOIN Customers c ON o.CustID = c.CustID — 可讀性、避免歧義、支援自我連接TABLESAMPLE:大表統計抽樣 FROM BigTable TABLESAMPLE (10 PERCENT)APPLY:逐列調用表值函數,解決「每類前 N 筆」等複雜邏輯=, <>, >, <, >=, <=, BETWEEN, LIKE, IN, EXISTS, IS NULLAND/OR 優先序:AND 高於 OR,善用括號| ❌ 非 SARGable | ✅ SARGable 改寫 | 原因 |
|---|---|---|
WHERE YEAR(OrderDate) = 2024 | WHERE OrderDate >= '2024-01-01' AND OrderDate < '2025-01-01' | 函數在欄位上阻礙索引 |
WHERE Name LIKE '%關鍵字%' | 全文檢索 / 前綴 LIKE '關鍵字%' | 前導萬用字元掃描 |
WHERE ISNULL(Status,0) = 1 | WHERE (Status = 1 OR Status IS NULL) | 函數包裹欄位 |
WHERE Col + 1 > 10 | WHERE Col > 9 | 運算在欄位上 |
GROUP BY
column_expression [ ,...n ]
| GROUPING SETS ( (col1), (col2, col3), () ) -- 多層次彙總 (SQL 2008+)
| ROLLUP (col1, col2) -- 階層小計
| CUBE (col1, col2) -- 交叉小計
未出現在 GROUP BY 的非彙總欄位 → 錯誤 (除非 ANY_VALUE 模式)。
SELECT
Region, Category,
SUM(Sales) AS TotalSales,
GROUPING_ID(Region, Category) AS GrpLevel -- 0=明細, 1=Category小計, 3=Region小計, 3=總計
FROM Sales
GROUP BY GROUPING SETS (
(Region, Category), -- 明細
(Region), -- 區域小計
(Category), -- 類別小計
() -- 總計
);
| 維度 | WHERE | HAVING |
|---|---|---|
| 執行階段 | 分組前 (列級) | 分組後 (群組級) |
| 可用彙總 | 否 | 是 |
| 別名引用 | 否 | 視版本 (建議重寫彙總) |
| 典型用途 | 業務篩選條件 | 彙總門檻過濾 |
-- 找出總銷售額超過 100萬 且 客戶數大於 50 的業務員
SELECT SalesRepID, SUM(Amount) AS TotalSales, COUNT(DISTINCT CustID) AS CustCount
FROM Orders
WHERE OrderDate >= '2024-01-01' -- 列級:時間範圍
GROUP BY SalesRepID
HAVING SUM(Amount) > 1000000 AND COUNT(DISTINCT CustID) > 50; -- 群組級:彙總門檻
SELECT
CustomerID, -- 5. SELECT
COUNT(*) AS OrderCount, -- 5. 彙總
MAX(OrderDate) AS LastOrder -- 5. 彙總
FROM Orders -- 1. FROM
WHERE Status = 'Completed' -- 2. WHERE
GROUP BY CustomerID -- 3. GROUP BY
HAVING COUNT(*) >= 5 -- 4. HAVING
ORDER BY OrderCount DESC; -- 6. ORDER BY
| 錯誤 | 現象 | 修正 |
|---|---|---|
| WHERE 用彙總 | WHERE COUNT(*) > 5 | 移至 HAVING |
| HAVING 用非彙總非分組欄位 | HAVING OrderDate > '2024-01-01' | 移至 WHERE |
| SELECT 含非分組非彙總欄位 | SELECT CustomerID, OrderDate ... GROUP BY CustomerID | 加入 GROUP BY 或用彙總 |
| 別名在 WHERE/HAVING 使用 | WHERE OrderCount > 5 | 重寫完整運算式 |
結語:嚴守執行順序與 SARGable 原則,查詢才能正確且高效。下一篇將進入視窗函數與進階分析查詢領域。