先准备数据: deptid :部门id. parent_deptid :deptid 的父级部门,也就是depid 是他的子部门。 create table test_employee (empid int ,deptid int ,parent_deptid int,salary decimal(10,2)); insert into test_employee values(1,10,100,5500.00); insert into test_employee values(2,10,200,4500.00); insert into test_employee values(3,20,100,1900.00); insert into test_employee values(4,20,200,4800.00); insert into test_employee values (5, 40,100, 6500.00); insert into test_employee values (6, 40,200, 14500.00); insert into test_employee values (7, 40,200, 44500.00); insert into test_employee values (8, 50,100, 6500.00); insert into test_employee values (9, 50,200, 7500.00); 假设说存在这么一个需求,需要获得所有子部门里薪水最高的那部分员工, 需要显示的字段有 empid, deptid,parent_deptid, salary 先简单介绍下这个sql中会遇到的一些关键的点: 1.row_number select rownum, te.* from test_employee te ; 以上sql语句将获得以下结果: ROWNUM EMPID DEPTID PARENT_DEPTID SALARY 1 **1 10 100 5500** 2 2 10 200 4500 3 3 20 100 1900 4 4 20 200 4800 5 5 40 100 6500 6 6 40 200 14500 7 7 40 200 44500 8 8 50 100 6500 9 9 50 200 7500 注意粗体部分,现在rownum 是1, 按如下sql来查: select rownum, te.* from test_employee te order by te.empid desc; 结果变成: ROWNUM EMPID DEPTID PARENT_DEPTID SALARY 1 2 10 200 4500 2 3 20 100 1900 3 4 20 200 4800 4 5 40 100 6500 5 6 40 200 14500 6 7 40 200 44500 7 8 50 100 6500 8 9 50 200 7500 empid为1 的记录不见了,但rownum 仍旧从1开始,也就说 rownum实际上就是查询自结果的一个逻辑排序。 2.利用分析函数(oracle)**row_number()以及**over()来分组筛选出符合条件的记录,注意在当rownumber与over()配合使 用时,是写法不一样的,注意粗体部分。 执行以下sql: select row_number()over(partition by te.deptid order by te.salary desc) rn, te.* from test_employee te order by empid ; 将会得到如下结果: RN EMPID DEPTID PARENT_DEPTID SALARY 1 1 10 100 5500 2 2 10 200 4500 2 3 20 100 1900 1 4 20 200 4800 3 5 40 100 6500 2 6 40 200 14500 1 7 40 200 44500 2 8 50 100 6500 1 9 50 200 7500 可以看出通过row_number()over(partition by te.deptid order by te.salary desc) rn这个分析函数已经通过deptid来分组 并通过薪水 来降序排列,那么在这个分组里薪水高的row_number将会是1,之后的 依次往后累加1,然后在通过查询以上上这个结果集,并加上条件rn=1 就能查出薪水最高的那位了,sql如下: select * from (select row_number()over(partition by te.deptid order by te.salary desc) rn, te.* from test_employee te)t1 where rn=1; RN EMPID DEPTID PARENT_DEPTID SALARY 1 1 10 100 5500 1 4 20 200 4800 1 7 40 200 44500 1 9 50 200 7500 如果想要得到薪水少的,只需要将分析函数中的order by desc 改成asc即可,那么薪水最低的RN 将会是1 select row_number()over(partition by te.deptid order by te.salary asc) rn, te.* from test_employee te order by empid ; RN EMPID DEPTID PARENT_DEPTID SALARY 2 1 10 100 5500 **1 2 10 200 4500** **1 3 20 100 1900** 2 4 20 200 4800 **1 5 40 100 6500** 2 6 40 200 14500 3 7 40 200 44500 **1 8 50 100 6500** 2 9 50 200 7500 select * from (select row_number()over(partition by te.deptid order by te.salary asc) rn, te.* from test_employee te)t1 where rn=1; RN EMPID DEPTID PARENT_DEPTID SALARY 1 2 10 200 4500 1 3 20 100 1900 1 5 40 100 6500 1 8 50 100 6500 同理如果要使用2个或以上字段来进行分组,上面的数据有点不对,一个 小部分只能属于一个大部门,稍微改下数据: drop table test_employee; create table test_employee (empid int ,deptid int ,gender varchar(1),salary decimal(10,2)); insert into test_employee values(1,10,'F',5500.00); insert into test_employee values(2,10,'M',4500.00); insert into test_employee values(3,10,'M',1900.00); insert into test_employee values(4,10,'F',4800.00); insert into test_employee values (5, 20,'M', 6500.00); insert into test_employee values (6, 20,'M', 14500.00); insert into test_employee values (7, 20,'F', 44500.00); insert into test_employee values (8, 20,'M', 6500.00); insert into test_employee values (9, 20,'F', 7500.00); 如假设存在以下条件,找出部门里的男女员工各自的最高薪(用一个sql语句查出): ROWNUM EMPID DEPTID GENDER SALARY 1 1 10 F 5500 2 2 10 M 4500 3 3 10 M 1900 4 4 10 F 4800 **5 5 20 M 6500** 6 6 20 M 14500 7 7 20 F 44500 **8 8 20 M 6500** 9 9 20 F 7500 select * from (select row_number()over(partition by te.deptid,gender order by te.salary desc) rn, te.* from test_employee te)t1 where rn=1; 结果如下: RN EMPID DEPTID GENDER SALARY 1 1 10 F 5500 1 2 10 M 4500 1 7 20 F 44500 1 6 20 M 14500 如果数据中同一分组存在两条相同的排序数据,如何处理(如都为6500,M,20部分的),先改成数据如下: ROWNUM EMPID DEPTID GENDER SALARY 1 1 10 F 5500 2 2 10 M 4500 3 3 10 M 1900 4 4 10 F 4800 5 5 20 M 6500 6 6 20 M 2500 7 7 20 F 44500 8 8 20 M 6500 9 9 20 F 7500 select * from (select row_number()over(partition by te.deptid,gender order by te.salary desc) rn, te.* from test_employee te)t1 where rn=1; 如下,empid=5 的被取出来了,原因是第一排序是salary,之后按empid默认升序排序: RN EMPID DEPTID GENDER SALARY 1 1 10 F 5500 1 2 10 M 4500 1 7 20 F 44500 **1 5 20 M 6500** 做个测试,再salary 后再加个empid 降序排列,那么是否应该empid=8的6500会被取出来? 查询结果如下: RN EMPID DEPTID GENDER SALARY 1 1 10 F 5500 1 2 10 M 4500 1 7 20 F 44500 **1 8 20 M 6500** 结果如我所想empid=8的将会被取出来。 总结: 以上不能用group by,因为select 只能是group by后的字段。 partition 是按部分字段分组的意思。