深入解析PostgreSQL窗口函数之frame_clause:RANGE、ROWS、GROUPS模式详解


窗口函数能在不改变数据行结构的前提下,基于分组或排序对数据进行动态聚合,是实现累计计算、滑动窗口、排名分析等复杂场景的核心技术。如果你还没有接触过窗口函数,建议先通过 PostgreSQL 官方文档搭建基础认知:从窗口函数入门教程理解核心概念,到窗口函数完整语法掌握基础用法,再通过窗口函数调用规范了解底层机制,这三步能为深入学习奠定基石。

  • 3.5. 窗口函数 http://www.postgres.cn/docs/current/tutorial-window.html
  • 9.22. 窗口函数 http://www.postgres.cn/docs/current/functions-window.html
  • 4.2.8. 窗口函数调用 http://www.postgres.cn/docs/current/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS

本文聚焦窗口函数的 “灵魂组件”——frame_clause,针对ROWS、RANGE、GROUPS三种帧定义模式,通过13个示例的程序代码、数据结果展示和详细的解析说明,帮你突破 “文档看得懂,写代码就懵” 的瓶颈。无论你是想厘清物理行偏移与逻辑值范围的本质区别,还是掌握分组滑动计算的高阶技巧,这些示例都能让你直观理解语法规则,真正将窗口函数转化为数据处理的高效武器。

一、基础概念与测试数据准备

1. 什么是frame_clause?

frame_clause用于在窗口分区内定义一个子集(窗口帧),窗口函数仅对该子集中的行生效。语法结构为:

OVER (
  [PARTITION BY ...] 
  ORDER BY ... 
  [frame_clause]
)

其中frame_clause有三种模式:RANGEROWSGROUPS,分别对应不同的行范围定义逻辑。

2. 测试数据创建

CREATE TABLE public.test_data (
    id INT,
    score INT,  -- 用于排序的数值列(测试RANGE/ROWS)
    value TEXT   -- 用于分组的文本列(测试GROUPS)
);

INSERT INTO public.test_data(id, score, value) VALUES
(1, 60, 'A'),
(2, 70, 'A'),
(3, 70, 'B'),
(4, 80, 'B'),
(5, 80, 'C'),
(6, 90, 'C');

-- 按score排序后的数据顺序
SELECT * FROM public.test_data ORDER BY score;
 id | score | value 
----+-------+-------
 1 |    60 | A
 2 |    70 | A
 3 |    70 | B
 4 |    80 | B
 5 |    80 | C
 6 |    90 | C

二、ROWS模式:基于物理行偏移的绝对位置

1. 核心规则

  • 偏移量offset表示物理行的数量,必须为非负整数。
  • 行范围:以当前行为中心,按ORDER BY排序后的物理行位置计算偏移。
  • 示例语法
    ROWS BETWEEN <start> AND <end>  -- 显式范围
    ROWS <offset> PRECEDING         -- 从当前行前offset行到当前行(默认end为CURRENT ROW)
    ROWS UNBOUNDED PRECEDING 		-- 默认,从分区开始到当前行
    

2. 案例演示

示例1:当前行 + 前后1行
SELECT 
    id, score,
    COUNT(*) OVER (
    	ORDER BY score 
    	ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
    ) AS row_count
FROM test_data 
ORDER BY score;
id score row_count 解释
1 60 2 – 仅第1行(60)和第2行(70),因为前面没有行,实际范围是1 PRECEDING(不存在)到1 FOLLOWI
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dudly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值