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

視窗函數入門到精通(一):核心概念、OVER 子句與聚合視窗函數實戰

     編輯:關於SqlServer

前言:解決 SQL 經典難題的利器

視窗函數在 SQL:2003 標準引入,SQL Server、Oracle、DB2 均支援(MySQL 8.0+ 才支援)。它解決了傳統聚合函數「每組只能返回一行」的限制,允許在保留明細行的同時計算聚合值,輕鬆解決「各組前 N 名」、「累計總額」、「同比環比」等經典問題。

核心概念:視窗 vs 群組

特性GROUP BY 聚合視窗函數
結果行數每組 1 行保留原始行數
明細資訊丟失保留
計算範圍整個群組可定義滑動視窗

語法結構


函數名(運算式) OVER (
  [PARTITION BY 分區欄位] 
  [ORDER BY 排序欄位] 
  [ROWS/RANGE 視窗框架]
)

建立測試資料


CREATE TABLE T_Person (
  FName VARCHAR(20),  -- 姓名
  FCity VARCHAR(20),  -- 城市
  FAge INT,           -- 年齡
  FSalary INT         -- 薪資
);

INSERT INTO T_Person VALUES
('Tom','BeiJing',20,3000), ('Tim','ChengDu',21,4000), ('Jim','BeiJing',22,3500),
('Lily','London',21,2000), ('John','NewYork',22,1000), ('YaoMing','BeiJing',20,3000),
('Swing','London',22,2000), ('Guo','NewYork',20,2800), ('YuQian','BeiJing',24,8000),
('Ketty','London',25,8500), ('Kitty','ChengDu',25,3000), ('Merry','BeiJing',23,3500),
('Smith','ChengDu',30,3000), ('Bill','BeiJing',25,2000), ('Jerry','NewYork',24,3300);

T_Person 測試資料

第一個視窗函數:COUNT(*) OVER()

需求:查詢薪資 < 5000 的員工,並顯示符合條件的總人數(每行皆顯示)。

傳統做法:子查詢


SELECT FCity, FAge, (SELECT COUNT(*) FROM T_Person WHERE FSalary < 5000) AS total_count
FROM T_Person WHERE FSalary < 5000;

子查詢結果

視窗函數做法:COUNT(*) OVER()


SELECT FCity, FAge, COUNT(*) OVER() AS total_count
FROM T_Person WHERE FSalary < 5000;

視窗函數結果

關鍵差異:OVER() 空括號表示視窗包含查詢結果集的所有行,聚合函數在此視窗上計算,結果廣播到每一行。

OVER 子句三大組件深度解析

1. PARTITION BY:分區(類 GROUP BY)

將結果集劃分為多個分區,視窗函數在各分區獨立計算。


-- 各城市薪資 < 5000 的員工人數
SELECT FCity, FAge, COUNT(*) OVER(PARTITION BY FCity) AS city_count
FROM T_Person WHERE FSalary < 5000;

2. ORDER BY:排序(決定視窗順序)

配合框架子句使用,定義「目前行之前/之後」的語意。

3. ROWS/RANGE:視窗框架(滑動窗口)


-- 依薪資排序,計算「目前行及之前所有行」的薪資累計
SELECT FName, FSalary, 
  SUM(FSalary) OVER(ORDER BY FSalary ROWS UNBOUNDED PRECEDING) AS running_total
FROM T_Person;

框架選項:

語法含義
ROWS UNBOUNDED PRECEDING從分區第一行到目前行
ROWS n PRECEDING目前行前 n 行到目前行
ROWS BETWEEN n PRECEDING AND m FOLLOWING自定義滑動範圍
RANGE按 ORDER BY 值範圍(而非行數)劃分

常用視窗函數分類

類別函數說明
聚合視窗函數SUM() OVER()累計、移動平均
AVG() OVER()移動平均
COUNT() OVER()分區計數
MAX()/MIN() OVER()分區極值
FIRST_VALUE()/LAST_VALUE()分區首/尾值
排序視窗函數ROW_NUMBER()唯一遞增序號
RANK()並列同名次,跳過下一名次
DENSE_RANK()並列同名次,不跳過
NTILE(n)分桶(如四分位數)
分析視窗函數LAG()/LEAD()存取前/後行值(同比環比神器)
PERCENT_RANK()相對排名百分位
CUME_DIST()累積分佈

實戰範例:各城市薪資前三名


WITH ranked AS (
  SELECT *, 
    ROW_NUMBER() OVER(PARTITION BY FCity ORDER BY FSalary DESC) AS rn
  FROM T_Person
)
SELECT FName, FCity, FSalary
FROM ranked
WHERE rn <= 3
ORDER BY FCity, FSalary DESC;

下一篇預告

下篇將深入講解 排序視窗函數(ROW_NUMBER/RANK/DENSE_RANK 差異陷阱)與 分析視窗函數(LAG/LEAD 同比環比實戰),敬請期待。

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