查看原文:http://ibloger.net/article/248.html

为了方便学习和测试,所有的例子都是在Oracle自带用户Scott下建立的。

create table EMP
(empno    NUMBER(4) not null,ename    VARCHAR2(10),job      VARCHAR2(9),mgr      NUMBER(4),hiredate DATE,sal      NUMBER(7,2),comm     NUMBER(7,2),deptno   NUMBER(2)
)
alter table EMPadd constraint PK_EMP primary key (EMPNO);insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7369, 'SMITH', 'CLERK', 7902, to_date('17-12-1980', 'dd-mm-yyyy'), 800, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7499, 'ALLEN', 'SALESMAN', 7698, to_date('20-02-1981', 'dd-mm-yyyy'), 1600, 300, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7521, 'WARD', 'SALESMAN', 7698, to_date('22-02-1981', 'dd-mm-yyyy'), 1250, 500, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7566, 'JONES', 'MANAGER', 7839, to_date('02-04-1981', 'dd-mm-yyyy'), 2975, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7654, 'MARTIN', 'SALESMAN', 7698, to_date('28-09-1981', 'dd-mm-yyyy'), 1250, 1400, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7698, 'BLAKE', 'MANAGER', 7839, to_date('01-05-1981', 'dd-mm-yyyy'), 2850, null, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7782, 'CLARK', 'MANAGER', 7839, to_date('09-06-1981', 'dd-mm-yyyy'), 2450, null, 10);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7788, 'SCOTT', 'ANALYST', 7566, to_date('19-04-1987', 'dd-mm-yyyy'), 3000, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7839, 'KING', 'PRESIDENT', null, to_date('17-11-1981', 'dd-mm-yyyy'), 5000, null, 10);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7844, 'TURNER', 'SALESMAN', 7698, to_date('08-09-1981', 'dd-mm-yyyy'), 1500, 0, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7876, 'ADAMS', 'CLERK', 7788, to_date('23-05-1987', 'dd-mm-yyyy'), 1100, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7900, 'JAMES', 'CLERK', 7698, to_date('03-12-1981', 'dd-mm-yyyy'), 950, null, 30);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7902, 'FORD', 'ANALYST', 7566, to_date('03-12-1981', 'dd-mm-yyyy'), 3000, null, 20);
insert into EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno) values (7934, 'MILLER', 'CLERK', 7782, to_date('23-01-1982', 'dd-mm-yyyy'), 1300, null, 10);

注:标题中的红色order by是说明在使用该方法的时候必须要带上order by

一、rank()/dense_rank() over(partition by ...order by ...)

现在客户有这样一个需求,查询每个部门工资最高的雇员的信息,相信有一定oracle应用知识的同学都能写出下面的SQL语句:

select * from (select ename, job, hiredate, e.sal, e.deptnofrom emp e,(select deptno, max(sal) sal from emp group by deptno) twhere e.deptno = t.deptnoand e.sal = t.sal)order by deptno;select * from (select ename 姓名, job 职业, hiredate 入职日期, e.sal 工资, e.deptno 部门from emp e,(select deptno, max(sal) sal from emp group by deptno) twhere e.deptno = t.deptnoand e.sal = t.sal)order by 部门;


在满足客户需求的同时,大家应该习惯性的思考一下是否还有别的方法。这个是肯定的,就是使用本小节标题中rank() over(partition by...)或dense_rank() over(partition by...)语法,SQL分别如下:

select empno, ename, job, hiredate, sal, deptnofrom (select empno, ename, job, hiredate, sal, deptno, rank() over(partition by deptno order by sal desc) r from emp)where r = 1;select empno, ename, job, hiredate, sal, deptnofrom (select empno, ename, job, hiredate, sal, deptno, dense_rank() over(partition by deptno order by sal desc) r from emp)where r = 1

为什么会得出跟上面的语句一样的结果呢?这里补充讲解一下rank()/dense_rank() over(partition by e.deptno order by e.sal desc)语法。
over:   在什么条件之上。
partition by e.deptno:   按部门编号划分(分区)。
order by e.sal desc:   按工资从高到低排序(使用rank()/dense_rank() 时,必须要带order by否则非法)
rank()/dense_rank():  分级
整个语句的意思就是:在按部门划分的基础上,按工资从高到低对雇员进行分级,“级别”由从小到大的数字表示(最小值一定为1)。

那么rank()和dense_rank()有什么区别呢?
rank(): 跳跃排序,如果有两个第一级时,接下来就是第三级。
dense_rank():  连续排序,如果有两个第一级时,接下来仍然是第二级。

小作业:查询部门最低工资的雇员信息。

二、min()/max() over(partition by ...)

现在我们已经查询得到了部门最高/最低工资,客户需求又来了,查询雇员信息的同时算出雇员工资与部门最高/最低工资的差额。这个还是比较简单,在第一节的groupby语句的基础上进行修改如下:

-- 查询每位雇员信息的同时算出雇员工资与所属部门最高/最低员工工资的差额

select ename 姓名, job 职业, hiredate 入职日期, e.deptno 部门, e.sal 工资, e.sal-me.min_sal 最低差额, me.max_sal-e.sal 最高差额from emp e, (select deptno, min(sal) min_sal, max(sal) max_sal from emp group by deptno) me  where e.deptno = me.deptno order by e.deptno, e.sal;  

上面我们用到了min()和max(),前者求最小值,后者求最大值。如果这两个方法配合over(partition by ...)使用会是什么效果呢?大家看看下面的SQL语句:

select ename 姓名, job 职业, hiredate 入职日期, deptno 部门, min(sal) over(partition by deptno) 部门最低工资, max(sal) over(partition by deptno) 部门最高工资 from emp order by deptno, sal;  select ename 姓名, job 职业, hiredate 入职日期, deptno 部门, nvl(sal - min(sal) over(partition by deptno), 0) 部门最低工资差额, nvl(max(sal) over(partition by deptno) - sal, 0) 部门最高工资差额from emp order by deptno, sal;

这两个语句的查询结果是一样的,大家可以看到min()和max()实际上求的还是最小值和最大值,只不过是在partition by分区基础上的。

小作业:如果在本例中加上order by,会得到什么结果呢?

三、lead()/lag() over(partition by ... order by ...)

中国人爱攀比,好面子,闻名世界。客户更是好这一口,在和最高/最低工资比较完之后还觉得不过瘾,这次就提出了一个比较变态的需求,计算个人工资与比自己高一位/低一位工资的差额。这个需求确实让我很是为难,在groupby语句中不知道应该怎么去实现。不过。。。。现在我们有了over(partition by ...),一切看起来是那么的简单。如下:

-- 计算个人工资与比自己高一位/低一位工资的差额

select ename 姓名, job 职业, sal 工资, deptno 部门,  lead(sal, 1, 0) over(partition by deptno order by sal)  比自己工资高的部门前一个,  lag(sal, 1, 0) over(partition by deptno order by sal)  比自己工资低的部门后一个,  nvl(lead(sal) over(partition by deptno order by sal) - sal, 0)  比自己工资高的部门前一个差额,   nvl(sal - lag(sal) over(partition by deptno order by sal), 0)   比自己工资高的部门后一个差额from emp;   

看了上面的语句后,大家是否也会觉得虚惊一场呢(惊出一身冷汗后突然鸡冻起来,这样容易感冒)?我们还是来讲解一下上面用到的两个新方法吧。
lead(列名,n,m):   当前记录后面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录后面第一行的记录<列名>的值,没有则默认值为null。
lag(列名,n,m):   当前记录前面第n行记录的<列名>的值,没有则默认值为m;如果不带参数n,m,则查找当前记录前面第一行的记录<列名>的值,没有则默认值为null。

下面再列举一些常用的方法在该语法中的应用(注:带order by子句的方法说明在使用该方法的时候必须要带order by):

select ename 姓名, job 职业, sal 工资, deptno 部门, first_value(sal) over(partition by deptno) first_sal, last_value(sal) over(partition by deptno) last_sal, sum(sal) over(partition by deptno) 部门总工资, avg(sal) over(partition by deptno) 部门平均工资, count(1) over(partition by deptno) 部门总数, row_number() over(partition by deptno order by sal) 序号 from emp;  

重要提示:大家在读完本片文章之后可能会有点误解,就是OVER (PARTITION BY ..)比GROUP BY更好,实际并非如此,前者不可能替代后者,而且在执行效率上前者也没有后者高,只是前者提供了更多的功能而已,所以希望大家在使用中要根据需求情况进行选择。

原文摘自:http://blog.csdn.net/fu0208/article/details/7179001

Oracle高级查询之over(partition by..)相关推荐

  1. Oracle高级查询之over(partition by...) 分组排序

    Oracle高级查询之over(partition by...) 分组排序 一.rank()/dense_rank() over(partition by ...order by ...) 现在客户有 ...

  2. 傅老师课堂:Oracle高级查询之OVER (PARTITION BY ..)

    [size=large][size=large][size=large]开篇一笑:某日一妹子对男友说:在一起这么久了你都没有夸过我漂亮,今天我要你夸夸我,男子想了一会看着女友鸡冻的说道:我硬了. 为了 ...

  3. 傅老师课堂:Oracle高级查询之OVER (PARTITION BY ..) 1

    为了方便大家学习和测试,所有的例子都是在Oracle自带用户Scott下建立的. 注:标题中的红色order by是说明在使用该方法的时候必须要带上order by. 一.rank()/dense_r ...

  4. Oracle高级查询之OVER (PARTITION BY ..)

    一.rank()/dense_rank() over(partition by ...order by ...) 查询每个部门工资最高的雇员的信息: 1. select e.ename, e.job, ...

  5. oracle高级查询案例,oracle高级查询(实例基于scott用户四张表)

    oracle高级查询(实例基于scott用户四张表) 分组查询 多表查询 子查询 综合实例 ====================================================== ...

  6. oracle—高级查询

    Sql基础 数据库语言 数据操纵语言:DML (data manipulation language) select insert update delete merge 数据定义语言:DDL(dat ...

  7. Oracle高级查询

    使用Oracle特有的查询语法, 可以达到事半功倍的效果 1. 树查询 create table tree (     id number(10) not null primary key,      ...

  8. by max over partition_Oracle高级查询之over(partition by...)

    为了方便学习和测试,所有的例子都是在Oracle自带用户Scott下建立的. create table EMP ( empno    NUMBER(4) not null, ename    VARC ...

  9. Oracle高级查询,over 用法

    注:标题中的红色order by是说明在使用该方法的时候必须要带上order by. 一.rank()/dense_rank() over(partition by ...order by ...) ...

最新文章

  1. linux 系统调用 read,write和lseek 使用
  2. 傅里叶变换中的狄利克雷条件
  3. linux中运行.sql文件
  4. unity3d游戏开发第2版 pdf_学开发2个月,1个人做出个TapTap排行榜第4的游戏?
  5. 动态规划(浅层基础)
  6. 函数调用的参数太少c语言,调用input_message的参数太少在主函数中 是神马意思 大神们帮帮我...
  7. tcp为什么要三次握手,而不能二次握手?
  8. C语言一元二次方程表示如下,C语言一元二次方程day6
  9. 重磅!英特尔终于挤出10nm芯片 六大技术战略,震动芯片届
  10. [转载] 用python统计中文字符数_使用Python统计字符串中各种字符的个数
  11. 作为PHP开发者请务必了解Composer
  12. python json提取器_入门python爬虫,10分钟就够了,这可能是我见过最简单的基础教学...
  13. solidity 中的时间_智能合约语言 Solidity 教程系列7 - 以太单位及时间单位
  14. uint在c语言中的作用,C中int,Uint,uint16等有什么区别以及用处
  15. 2020中国云计算行业研究报告 附下载地址
  16. Nginx负载均衡探活max_fails和fail_timeout的设置、根据参数转发upstream
  17. ipad打开网页无法播放视频
  18. 【菜鸟学习论文】2020_Cascade Cost Volume for High-Resolution Multi-View Stereo and Stereo Matching
  19. Ubuntu16.04:GTX1650的显卡驱动安装
  20. IDL CMIP6 NC格式数据处理

热门文章

  1. 什么是张量 (tensor)?
  2. python3黑帽编程_Python3.7 黑帽编程
  3. 自己实现的php加密解密函数结果纯字母和数字
  4. MTK平台 在lk阶段,读取IMEI号
  5. 一文学会,三款黑客必备的抓包工具教学(实在太强了,总有一款适合你)
  6. 土壤水分传感器的工作原理和应用环境
  7. 按键精灵--多点找色浅谈
  8. C/C++ 基于对勾函数和双曲线实现高效率散列函数,实现真正意义上的减少冲突!!
  9. 服务器w8系统如何重装系统,如何重装Windows8.1 Win8.1系统重装流程图解
  10. Python实现一个论文下载器