oracle row_number()over() 函数运用

本文深入探讨了SQL窗口函数的使用方法,包括累计求和、分组内排序求和、部门内累计求和及排序、按部门和薪水排序、部门内薪水排名及查找部门薪水最高员工等内容。

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

row_number() over ([partition by col1] order by col2) ) as 别名
表示根据col1分组,在分组内部根据 col2排序
而这个“别名”的值就表示每组内部排序后的顺序编号(组内连续的唯一的),[partition by col1] 可省略。

以Scott/tiger登陆,以emp表为例。

1、select deptno,ename,sal,
sum(sal) over (order by ename) 累计, --按姓名排序,并将薪水逐个累加
sum(sal) over () 总和 , -- 此处sum(sal) over () 等同于sum(sal),求薪水总和
100*round(sal/sum(sal) over (),4) "份额(%)" --求每个人的薪水占总额的比例,小数点后保留2位,括号和百分号为特殊符号,所以需要“”
from emp

结果如下 :
[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/f2598dedc472bc3f63d09f66.jpg[/img]

2、select deptno,ename,sal,
sum(sal) over (partition by deptno order by ename) 部门连续求和,--partition by deptno先按部门分组,再按姓名排序,并将薪水逐个累加
sum(sal) over (partition by deptno) 部门总和, -- 每个部门的薪水总和
100*round(sal/sum(sal) over (partition by deptno),4) "部门份额(%)",--每个员工在各自部门的薪水比例
sum(sal) over (order by deptno,ename) 连续求和, --所有部门的薪水"连续"求和
sum(sal) over () 总和, -- 此处sum(sal) over () 等同于sum(sal),所有员工的薪水总和
100*round(sal/sum(sal) over (),4) "总份额(%)" --求每个人的薪水占总额的比例
from emp

结果如下:
[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/4400ed169f5bb811c83d6d62.jpg[/img]

3、select deptno,ename,sal,sum(sal) over (partition by deptno order by sal) dept_sum,--根据部门分组,再按部门内的个人薪水排序,逐个累加。
sum(sal) over (order by deptno,sal) sum --按部门排序,将薪水逐个累加。
from emp;

结果如下:
[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/8156d302c3e47ff409fa9368.jpg[/img]

4、部门从大到小排列,部门里各员工的薪水从高到低排列

select deptno,ename,sal,
sum(sal) over (partition by deptno order by deptno desc,sal desc) dept_sum,--按部门分组后,按部门和薪水降序排
sum(sal) over (order by deptno desc,sal desc) sum --按部门和薪水降序排
from emp;

结果如下:
[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/e9d39718cbaa685d42a9ad6b.jpg[/img]


5、将各部门的员工按薪水排序

select ename,job,deptno,sal,(row_number() over(partition by deptno order by sal desc)) as 排名 --先按部门分组,再在部门中按薪水降序排名
from scott.emp

结果如下:
[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/332428f5a7f714f77609d79f.jpg[/img]

6、查找各部门中薪水最高的前2位

select ename,job,deptno,sal,排名 from
(select ename,job,deptno,sal,(row_number() over(partition by deptno order by sal desc)) as 排名
from scott.emp --先将各部门的员工按薪水排序,再在结果中取出需要的部分
) where 排名<=2;

结果如下:

[img]http://hiphotos.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/pic/item/4ee8f9c5ad825ed339db499d.jpg[/img]

7、如果已经在over()中进行过分组,在"... from emp;"后面不要加order by 子句。
<think>好的,我现在需要帮助用户理解Oracle数据库ROW_NUMBER() OVER的用法。根据用户的问题,他们想要具体的示例和语法说明。首先,我得回忆一下相关的知识,确保自己正确掌握这个函数的使用方法。 首先,ROW_NUMBER()是一个窗口函数,用于给查询结果中的每一行分配一个唯一的序号。用户可能需要了解它的基本语法结构。我记得语法大致是ROW_NUMBER() OVER后面跟着PARTITION BY和ORDER BY子句。需要确认是否正确,比如PARTITION BY用于分组,ORDER BY决定排序方式,这样每个分区内的行会按指定的顺序编号。 接下来,用户可能需要具体的示例来理解不同的应用场景。比如分页查询,这是常见的用途,类似于MySQL中的LIMIT和OFFSET。这时候需要用子查询,外层根据ROW_NUMBER的值来筛选。例如,获取第4到第6名的记录,需要在内层查询中使用ROW_NUMBER() OVER,然后在外层使用BETWEEN。 然后,数据去重也是一个应用场景。当数据有重复时,可以使用PARTITION BY指定重复的字段,按某个条件排序,然后取rn=1的行,这样每组重复数据只保留一条。例如,按员工邮箱分组,按入职时间降序排列,保留最新的记录。 还有排名问题,比如每个部门内按薪资排名。这时候需要PARTITION BY部门,ORDER BY薪资降序,这样每个部门内的员工都会有独立的排名。用户可能需要这样的例子来理解分组内的排序。 此外,需要注意ROW_NUMBER()的执行顺序,它是在WHERE、GROUP BY、ORDER BY之后执行的。这点很重要,因为在写查询的时候要确保先筛选和分组,再计算行号。例如,如果先过滤数据,再使用ROW_NUMBER(),结果会更准确。 用户提供的引用资料中提到了分页查询、去重、排名等案例,我需要将这些内容整合到回答中,确保涵盖这些方面。同时,要检查语法是否正确,比如OVER子句的结构,是否需要用别名,子查询的处理等。 可能还需要提醒用户注意性能问题,尤其是在处理大数据量时,合理的索引和分区策略可以提高效率。此外,ROW_NUMBER()与其他排名函数如RANK()和DENSE_RANK()的区别也是常见的疑问,但用户没有提到,可能暂时不需要深入,但可以提到以供进一步探索。 最后,生成相关问题的时候,要考虑用户可能进一步想知道的内容,比如优化方法、执行原理或与其他函数的对比。这些问题可以帮助用户深入学习和解决问题。 总结一下,回答的结构应该是先语法说明,再分应用场景举例,每个场景给出示例和解释,最后注意事项和相关问题。需要确保使用正确的中文表达,LaTeX公式正确,行内公式用$,独立公式用$$,并检查代码块格式是否正确。</think>以下是对Oracle数据库中$ROW\_NUMBER()\ OVER$函数的详细说明及使用示例: ### 一、语法结构 $$ROW\_NUMBER()\ OVER\ (\ [PARTITION\ BY\ column]\ ORDER\ BY\ column\ [ASC|DESC]\ )$$ - $PARTITION\ BY$:定义分组字段(可选),实现分组内独立排序 - $ORDER\ BY$:指定排序字段及顺序(必选) ### 二、使用场景及示例 #### 1. 分页查询(核心应用) ```sql SELECT * FROM ( SELECT employee_id, name, salary, ROW_NUMBER() OVER (ORDER BY hire_date DESC) AS rn FROM employees ) WHERE rn BETWEEN 11 AND 20; -- 获取第11-20条记录[^2] ``` #### 2. 数据去重 ```sql SELECT * FROM ( SELECT email, create_time, ROW_NUMBER() OVER ( PARTITION BY email ORDER BY create_time DESC ) AS rn FROM user_logs ) WHERE rn = 1; -- 保留最新记录[^3] ``` #### 3. 分组排名 ```sql SELECT department_id, employee_name, salary, ROW_NUMBER() OVER ( PARTITION BY department_id ORDER BY salary DESC ) AS dept_rank FROM employees; -- 部门薪资排名[^4] ``` ### 三、执行原理说明 1. 该函数在WHERE/GROUP BY/HAVING之后执行 2. 计算结果不受外层ORDER BY影响 3. 必须配合OVER子句使用 ### 四、注意事项 - 相同排序值时序号仍递增(区别于$RANK()$) - 分页查询需嵌套子查询 - 大数据量建议配合索引使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值