让你少走弯路的MySQL中rank()、row_number()、dense_rank()排序

create table students(
	id int(4)  auto_increment primary key,
	name varchar(50) not null, 
	score int(4) not null
	);

先简单的创建一个测试用的表,将数据插入表中。

insert into students(name,score) values('curry', 100),
	('klay', 99),
	('KD', 100), 
	('green', 90), 
	('James', 99), 
	('AD', 96);

查看一下插入的数据:

select * from students;

 

开始使用三种不同的方法进行排序:

select id, name, rank() over(order by score desc) as r from students;
select id, name, DENSE_RANK() OVER(order by score desc) as dense_r from students;
select id, name, row_number() OVER(order by score desc) as row_r from students;

当然也可以写在同一张表中:

select id, name, rank() over(order by score desc) as r,
	DENSE_RANK() OVER(order by score desc) as dense_r,
	row_number() OVER(order by score desc) as row_r
from students;

需要注意的一点是as后的别名,千万不要与前面的函数名重名,否则会报错。

结果是很清楚的,具体就不解释了,相信大家看到结果都 很清楚三种排序的差别了。

 

 

 

 

<think>好的,用户现在想了解SQL中的开窗函数。之前他们问过LeetCode的Plus会员专享题,现在转向技术问题,可能是正在学习SQL,准备面试或者工作中需要用到。 开窗函数在SQL中确实是一个重要但可能有点复杂的主题,尤其是对于刚接触的人来说。用户可能已经掌握了基本的聚合函数,比如SUM和AVG,但发现需要在不合并行的情况下进行聚合,这时候开窗函数就派上用场了。 我需要先确定用户的基础知识水平。他们可能知道GROUP BY,但可能不清楚它与开窗函数的区别。所以在解释时,要对比这两者,强调开窗函数不会减少行数,而是添加计算结果作为新列。 接下来,需要解释开窗函数的基本结构,包括OVER子句、PARTITION BY、ORDER BY和窗口框架。这些是核心概念,必须清晰明了。可能需要用例子来说明,比如按部门分区计算平均工资,或者计算累计销售额。 用户可能想知道开窗函数的常见用途,比如排名、累加、移动平均等。这时候举一些实际例子会很有帮助,比如ROW_NUMBERRANKDENSE_RANK的区别,或者LEAD和LAG函数的使用场景。 还要注意常见的函数分类,比如聚合函数、排名函数、分布函数和前后函数。每个类别举一两个例子,帮助用户理解不同函数的作用。 可能用户在使用开窗函数时遇到的常见问题,比如窗口范围的定义,或者性能问题。虽然用户没有直接问这些,但提前指出可以避免他们走弯路。比如,提到ORDER BY对窗口框架的影响,或者大数据量下的注意事项。 另外,用户可能关心不同数据库的支持情况,比如MySQL、PostgreSQL、SQL Server等是否都支持开窗函数。不过这个问题可能超出当前范围,但可以简要提到大多数现代数据库都支持,具体语法可能略有不同。 总结时,要强调开窗函数的优势,比如灵活性,能够在单次查询中同时获取详细数据和聚合结果,这对于生成报告或数据分析非常有用。同时,提醒用户根据实际需求选择合适的函数,避免过度使用导致查询性能下降。 最后,确保整个解释结构清晰,分点说明,用例子辅助理解,并且语言通俗易懂,避免过于技术性的术语,除非必要。检查是否有遗漏的重要概念,比如窗口框架中的ROWS和RANGE区别,或者FILTER子句的使用,但根据用户的提问深度,可能暂时不需要深入这些细节,保持回答简洁即可。</think>好的!SQL中的**开窗函数**(Window Function)是一种高级查询功能,允许在数据集的特定“窗口”(即行的子集)上执行计算,同时保留原始行的细节。它与普通聚合函数(如`SUM`、`AVG`)的关键区别在于:**开窗函数不会合并多行结果,而是为每一行生成独立的值**。 --- ### 一、核心概念与语法 #### 1. **基本结构** ```sql 函数名([参数]) OVER ( [PARTITION BY 分区字段] -- 定义窗口的分组依据(类似GROUP BY,但不聚合) [ORDER BY 排序字段] -- 定义窗口内的排序规则 [窗口框架] -- 定义窗口范围(如当前行前后多少行) ) ``` #### 2. **常用开窗函数** | 类型 | 函数示例 | 用途 | |----------------|---------------------------|--------------------------------------| | **聚合函数** | `SUM()`, `AVG()`, `COUNT()` | 在窗口内计算聚合值(保留原始行) | | **排名函数** | `ROW_NUMBER()`, `RANK()` | 生成排名、序号 | | **分布函数** | `PERCENT_RANK()`, `CUME_DIST()` | 计算百分比排名或累积分布 | | **前后函数** | `LAG()`, `LEAD()` | 访问窗口内其他行的值(如前一行数据) | --- ### 二、典型使用场景 #### 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 employee_id, sale_date, amount, SUM(amount) OVER ( PARTITION BY employee_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS cumulative_sales FROM sales; ``` #### 3. **排名与分组比较** **示例**:按部门对员工工资排名。 ```sql SELECT name, department, salary, RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS salary_rank FROM employees; ``` --- ### 三、窗口框架(Window Frame) 通过`ROWS`或`RANGE`定义窗口范围,常见用法: - `ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING`:当前行的前一行到后一行。 - `ROWS UNBOUNDED PRECEDING`:从第一行到当前行(常用于累计计算)。 --- ### 四、与普通聚合函数的区别 | 特性 | 普通聚合函数(如`GROUP BY`) | 开窗函数 | |------------------|------------------------------|------------------------------| | **行数变化** | 合并为分组后的行 | 保留原始行数 | | **结果可见性** | 仅显示分组后的汇总结果 | 显示每行的详细数据+聚合结果 | | **性能影响** | 通常更快 | 可能更复杂(需排序和分区) | --- ### 五、常见问题 1. **何时必须使用开窗函数?** 需要同时展示明细数据和聚合结果时(如计算每行的排名或累计值)。 2. **是否所有数据库都支持开窗函数?** 主流数据库(如PostgreSQL、MySQL 8.0+、SQL Server、Oracle)均支持。 3. **性能优化建议** - 避免在`PARTITION BY`或`ORDER BY`中使用复杂表达式。 - 对大数据量场景,优先使用`ROWS`而非`RANGE`(后者可能更耗资源)。 --- ### 六、总结 开窗函数极大地扩展了SQL的分析能力,适用于: - 动态排名与分组比较 - 累计计算(如移动平均、累计求和) - 跨行数据访问(如前/后值对比) 合理使用可以避免复杂的子查询或多次表连接,让查询逻辑更简洁高效!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值