postgres 窗口函数

本文详细介绍了Window Function中的多种函数,如row_number(), rank(), dense_rank(), percent_rank(), cume_dist(), ntile(), lag(), lead(), first_value(), last_value(), nth_value()等,并通过一个具体的SQL查询示例展示了这些函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Window Function
* row_number() bigint number of the current row within its partition, counting from 1

  • rank() bigint rank of the current row with gaps; same as row_number of its first peer

  • dense_rank() bigint rank of the current row without gaps; this function counts peer groups

  • percent_rank() double precision relative rank of the current row: (rank - 1) / (total rows - 1)

  • cume_dist() double precision relative rank of the current row: (number of rows preceding or peer with current row) / (total rows)

  • ntile(num_buckets integer) integer integer ranging from 1 to the argument value, dividing the partition as equally as possible

  • lag(value any [, offsetinteger [, default any ]]) same type as value returns value evaluated at the row that is offset rows before the current row within the partition; if there is no such row, instead return default. Bothoffset and default are evaluated with respect to the current row. If omitted, offset defaults to 1 and default to null

  • lead(value any [, offsetinteger [, default any ]]) same type as value returns value evaluated at the row that is offset rows after the current row within the partition; if there is no such row, instead return default. Bothoffset and default are evaluated with respect to the current row. If omitted, offset defaults to 1 and default to null

  • first_value(value any) same type as value returns value evaluated at the row that is the first row of the window frame

  • last_value(value any) same type as value returns value evaluated at the row that is the last row of the window frame

  • nth_value(value any, nthinteger) same type as value returns value evaluated at the row that is the nth row of the window frame (counting from 1); null if no such row

postgres=# select depname, empno, salary, row_number() over() from empsalary;
 depname | empno | salary | row_number
----------+-------+--------+------------
 develop  | 11 | 5200 | 1
 develop  | 7  | 4200 | 2
 develop  | 9  | 4500 | 3
 personel | 5  | 3500 | 4
 personel | 6  | 6500 | 5
 personel | 12 | 6500 | 6
 personel | 15 | 8900 | 7
<think>我们正在回答用户关于PostgreSQL窗口函数的问题。根据提供的引用资料,我们需要总结窗口函数的基本概念、语法结构,并给出示例教程。注意:用户要求使用中文回答,并且按照给定的格式要求(行内数学公式用$...$,独立公式用$$...$$,生成相关问题等)。步骤:1.介绍窗口函数的概念,强调其与聚合函数的区别(窗口函数不将多行聚合成一行,而是保留原有行)。2.解释窗口函数的语法结构,包括OVER子句、PARTITION BY、ORDERBY以及窗口帧(frame_clause)等。3.给出几个常见的窗口函数示例(如row_number(), rank(), dense_rank(), sum()over()等)并解释。4.提供示例SQL语句和预期结果,帮助用户理解。5.生成相关问题。注意:引用资料中提供了多个来源,我们在回答中适当引用。开始回答:</think>### PostgreSQL 窗口函数使用指南 #### 一、基本概念 窗口函数(Window Function)允许在查询结果集的**指定行子集**(窗口)上执行计算,同时保留所有原始行。与聚合函数不同,窗口函数**不会合并多行结果**,而是为每行返回独立计算结果[^3][^4]。 核心语法结构: ```sql 函数名(表达式) OVER ( [PARTITION BY 分组字段] [ORDER BY 排序字段 [ASC|DESC]] [窗口帧子句] ) ``` #### 二、核心语法详解 1. **`PARTITION BY`** 将数据按指定字段分组,函数在**每个分组内独立计算**。 ```sql -- 按部门分组计算平均薪资 SELECT name, department, salary, AVG(salary) OVER (PARTITION BY department) AS dept_avg_salary FROM employees; ``` 2. **`ORDER BY`** 定义窗口内数据的**计算顺序**,常用于累计计算: ```sql -- 按时间累计销售额 SELECT order_date, amount, SUM(amount) OVER (ORDER BY order_date) AS running_total FROM sales; ``` 3. **窗口帧子句** 指定函数计算的具体范围: - `ROWS BETWEEN N PRECEDING AND M FOLLOWING`:物理行偏移 - `RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW`:逻辑值范围 ```sql -- 计算7天移动平均 SELECT date, revenue, AVG(revenue) OVER ( ORDER BY date RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND CURRENT ROW ) AS moving_avg FROM daily_sales; ``` #### 三、常用窗口函数示例 | 函数类型 | 示例函数 | 用途说明 | |----------------|---------------------------|------------------------------| | 排名函数 | `ROW_NUMBER()` | 生成分组内连续序号 | | | `RANK()` | 允许并列排名(跳号) | | | `DENSE_RANK()` | 允许并列排名(不跳号) | | 聚合类窗口函数 | `SUM() OVER()` | 分组累计求和 | | | `AVG() OVER()` | 分组移动平均 | | 分布函数 | `PERCENT_RANK()` | 计算百分比排名 | | 前后行访问 | `LAG(column, n)` | 访问前n行数据 | #### 四、完整示例教程 ```sql -- 示例表:员工薪资数据 CREATE TABLE employees ( id SERIAL PRIMARY KEY, name VARCHAR(50), department VARCHAR(50), salary NUMERIC ); -- 查询:计算部门内薪资排名及与部门平均薪资的差异 SELECT name, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank, salary - AVG(salary) OVER (PARTITION BY department) AS diff_from_avg FROM employees; ``` **结果示例**: | name | department | salary | dept_rank | diff_from_avg | |-------|------------|--------|-----------|---------------| | Alice | HR | 8000 | 1 | +2000 | | Bob | HR | 6000 | 2 | 0 | | Carol | IT | 9000 | 1 | +1500 | #### 五、关键技巧 1. **多层窗口**:可定义命名窗口复用配置 ```sql SELECT *, SUM(x) OVER w1, AVG(y) OVER w2 FROM table WINDOW w1 AS (PARTITION BY a ORDER BY b), w2 AS (w1 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW); ``` 2. **`FILTER`子句**:仅对符合条件的行计算 ```sql SELECT department, AVG(salary) FILTER (WHERE salary > 5000) OVER () AS high_salary_avg FROM employees; ``` > **注意**:窗口函数在`SELECT`子句执行阶段计算,**不可用于`WHERE`或`GROUP BY`** 子句[^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值