1. row_number() over()
语法
ROW_NUMBER() OVER(PARTITION BY COLUMN1 ORDER BY COLUMN2 [desc])
根据column1分组,根据column2排序
2.具体事例
如下,我们通过具体实例进行理解分析。
有如下一张表:
create table LJB_TEST
(
dep NUMBER,
name VARCHAR2(50),
salary NUMBER
);
insert all
into ljb_test values('1','start','5000')
into ljb_test values('1','ha','5000')
into ljb_test values('1','end','4000')
into ljb_test values('1','begin','4500')
into ljb_test values('2','ri','4000')
into ljb_test values('2','zhou','6000')
into ljb_test values('2','yue','3000')
into ljb_test values('3','kettle','4000')
into ljb_test values('3','oracle','4000')
into ljb_test values('3','hive','4000')
into ljb_test values('3','mysql','4000')
into ljb_test values('3','plsql','5000')
select 1 from dual
;
commit;
我们有如下需求:
2.1.计算每个部门薪水值前二的的人员。
自然的,我们根据部门分组,根据薪水降序,取前两个。
我们通过SQL实现上述想法。
select * from
(
select
t.*,
row_number() over(partition by dep order by salary desc) rn
from ljb_test t
)t
where t.rn<=2
;
不过,我们很自然的发现,很多人的薪水是相同的,因而,实际上薪水值前二的员工并不代表是两个员工。也就是说,我们要查的是薪水>=某个值的记录。
因此,我们将自己的想法通过SQL实现。
with tmp
as
(
select dep,salary from
(
select
dep,salary,
row_number() over(partition by dep order by salary desc) rn
from ljb_test t
)t
where t.rn=2
)
select
t.*
from ljb_test t
inner join
tmp
on t.dep = tmp.dep
and t.salary>=tmp.salary
order by t.dep,t.salary desc
2.2.计算前百分之几。
如下,我们需要计算每个部门薪水前50%的员工信息,且如果不满两人,取第一个人薪水。
这个问题的核心就是找出每组的50%的分水岭(前10%的逻辑一样)。
如下:
with tmp as
(
select
dep,salary,
row_number() over(partition by dep order by salary desc) rn
from ljb_test t
)
select tmp.dep,tmp.salary
from tmp
inner join
(
select tmp.dep,tmp.salary
from tmp
--2.关联获得50%的薪水值
inner join
(
--1.算出前50%的每组的row_number()
select t.dep, round(case when count(*)*0.5<1 then 1 else count(*)*0.5 end,0) ct
from ljb_test t
group by t.dep
)tt
on tmp.dep = tt.dep and tmp.rn = tt.ct
)ttt
on tmp.dep = ttt.dep and tmp.salary >= ttt.salary