先准备数据:
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 是按部分字段分组的意思。
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 是按部分字段分组的意思。