首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL 語法全面進階 (四):HAVING、GROUP BY、FROM、WHERE 子句深度解析

     編輯:關於SqlServer

查詢結構四大支柱:FROM → WHERE → GROUP BY → HAVING 執行邏輯與實戰模式

理解子句執行順序 (FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY) 是撰寫正確、高效查詢的前提。本文深度解析四大核心子句語法、常見錯誤與優化模式。

一、FROM — 資料來源與連接

語法擴展

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 筆」等複雜邏輯

二、WHERE — 列級篩選

核心規則

  • 作用於 分組前 的資料列,不可使用彙總函數
  • 支援所有運算子:=, <>, >, <, >=, <=, BETWEEN, LIKE, IN, EXISTS, IS NULL
  • 多條件 AND/OR 優先序:AND 高於 OR,善用括號

SARGable (Search ARGument Able) 原則 — 索引求取關鍵

❌ 非 SARGable✅ SARGable 改寫原因
WHERE YEAR(OrderDate) = 2024WHERE OrderDate >= '2024-01-01' AND OrderDate < '2025-01-01'函數在欄位上阻礙索引
WHERE Name LIKE '%關鍵字%'全文檢索 / 前綴 LIKE '關鍵字%'前導萬用字元掃描
WHERE ISNULL(Status,0) = 1WHERE (Status = 1 OR Status IS NULL)函數包裹欄位
WHERE Col + 1 > 10WHERE Col > 9運算在欄位上

三、GROUP BY — 分組彙總

語法與規則

GROUP BY 
    column_expression [ ,...n ]
  | GROUPING SETS ( (col1), (col2, col3), () )  -- 多層次彙總 (SQL 2008+)
  | ROLLUP (col1, col2)                         -- 階層小計
  | CUBE (col1, col2)                           -- 交叉小計

鐵律:SELECT 清單 = GROUP BY 清單 + 彙總函數

未出現在 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),          -- 類別小計
    ()                   -- 總計
);

四、HAVING — 群組級篩選

與 WHERE 本質差異

維度WHEREHAVING
執行階段分組前 (列級)分組後 (群組級)
可用彙總否是
別名引用否視版本 (建議重寫彙總)
典型用途業務篩選條件彙總門檻過濾

實戰範例

-- 找出總銷售額超過 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 原則,查詢才能正確且高效。下一篇將進入視窗函數與進階分析查詢領域。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved