SQL Server 窗口函数简介

SQL Server 中的窗口函数(Window Functions)是一种强大的分析函数,它允许你在查询结果集中对某一"窗口"(即一组相关行)进行计算,同时保留每一行的细节。与普通的聚合函数(如 SUM、COUNT)不同,窗口函数不会将行分组合并成一条,而是为每一行计算结果,非常适合排名、累计统计、移动平均等场景。

窗口函数的核心语法是:

sql 复制代码
函数名(表达式) OVER (
    [PARTITION BY 列1, 列2, ...]   -- 可选:分组(类似 GROUP BY)
    [ORDER BY 列1 [ASC|DESC], ...] -- 可选:排序(决定窗口的顺序)
    [ROWS|RANGE 子句]              -- 可选:定义窗口帧(默认 UNBOUNDED PRECEDING AND CURRENT ROW)
)
  • PARTITION BY:将数据分成多个分区,每个分区独立计算(类似分组)。
  • ORDER BY:定义窗口内的行顺序,很多函数需要它来决定"前后行"。
  • ROWS/RANGE:精确控制窗口的行范围(如前几行、当前行等)。
常见窗口函数分类
  1. 排名函数

    • ROW_NUMBER():为每行分配唯一序号。
    • RANK():排名,有并列时跳号(如 1、1、3)。
    • DENSE_RANK():排名,有并列时不跳号(如 1、1、2)。
    • NTILE(n):将数据分成 n 组。
  2. 聚合窗口函数

    • SUM()、AVG()、COUNT()、MAX()、MIN() 等,可以带 OVER 子句做累计或分区统计。
  3. 值函数

    • LAG(列, n):取前 n 行的值。
    • LEAD(列, n):取后 n 行的值。
    • FIRST_VALUE(列):分区内第一个值。
    • LAST_VALUE(列):分区内最后一个值。
示例

假设我们有一张销售表 Sales

sql 复制代码
CREATE TABLE Sales (
    SalesID INT,
    Region NVARCHAR(20),
    SalesDate DATE,
    Amount DECIMAL(10,2)
);

INSERT INTO Sales VALUES
(1, 'North', '2025-01-01', 1000),
(2, 'North', '2025-01-05', 1500),
(3, 'South', '2025-01-02', 800),
(4, 'South', '2025-01-06', 1200),
(5, 'North', '2025-01-10', 2000);

示例 1:ROW_NUMBER() 按区域和日期排名

sql 复制代码
SELECT 
    Region,
    SalesDate,
    Amount,
    ROW_NUMBER() OVER (PARTITION BY Region ORDER BY Amount DESC) AS RowNum
FROM Sales;

结果:

Region SalesDate Amount RowNum
North 2025-01-10 2000 1
North 2025-01-05 1500 2
North 2025-01-01 1000 3
South 2025-01-06 1200 1
South 2025-01-02 800 2

每个区域内按销售额从高到低编号。

示例 2:累计销售额(SUM OVER)

sql 复制代码
SELECT 
    Region,
    SalesDate,
    Amount,
    SUM(Amount) OVER (PARTITION BY Region ORDER BY SalesDate 
                      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal
FROM Sales;

结果(North 区域的累计):

Region SalesDate Amount RunningTotal
North 2025-01-01 1000 1000
North 2025-01-05 1500 2500
North 2025-01-10 2000 4500

显示每个区域内按日期排序的累计销售额。

示例 3:LAG/LEAD 取前后值

sql 复制代码
SELECT 
    Region,
    SalesDate,
    Amount,
    LAG(Amount, 1) OVER (PARTITION BY Region ORDER BY SalesDate) AS PrevAmount,
    LEAD(Amount, 1) OVER (PARTITION BY Region ORDER BY SalesDate) AS NextAmount
FROM Sales;

可以查看每笔销售的前一笔和后一笔金额。

窗口函数极大提升了 SQL 的分析能力,在报表、排行榜、时间序列分析等场景中非常实用。

相关推荐
java_logo1 小时前
Apache Doris Docker 部署指南:实时分析数据库实战
数据库·docker·apache·doris·apache doris·轩辕镜像·docker部署doris
To_OC7 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
灯澜忆梦8 小时前
GO_并发编程---定时器
开发语言·后端·golang
-银雾鸢尾-8 小时前
C#中的StringBuilder相关方法
开发语言·c#
To_OC8 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
小林ixn9 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
-银雾鸢尾-9 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
广州灵眸科技有限公司9 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
এ慕ོ冬℘゜9 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
大模型码小白10 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程