row_number() over()计算每组前几个和前百分之几

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

猜你喜欢

转载自blog.csdn.net/qq_36743482/article/details/79153882