row_number() over partition by 分組聚合


分組聚合,就是先分組再排序,可以的話順手標個排名;如果不想分組也可以排名;如果不想分組同時再去重排名也可以

ROW_NUMBER() OVER(
    [PARTITION BY column_1, column_2,…]
    [ORDER BY column_3,column_4,…]
)

Oracle和SQL server的關鍵字是over partition by

mysql的無關鍵字row_number() over (partition by col1 order by col2),表示根據col1分組,在分組內部根據col2排序

Oracle和sqlserver

最終效果:

Image

例子:

-- 建表
USE db_03;
DROP TABLE IF EXISTS employee;
create table employee (empid int ,deptid int ,salary decimal(10,2));
insert into employee values(1,10,5500.00);
insert into employee values(2,10,4500.00);
insert into employee values(3,20,1900.00);
insert into employee values(4,20,4800.00);
insert into employee values(5,40,6500.00);
insert into employee values(6,40,14500.00);
insert into employee values(7,40,44500.00);
insert into employee values(8,50,6500.00);
insert into employee values(9,50,7500.00);

SELECT * FROM employee;

Image [1]

SELECT *, Row_Number() OVER (partition by deptid ORDER BY salary desc) rank FROM employee

結果:

Image [2]

如果不要分組,就僅僅order by 的話

需求:給username加上唯一標示id

背景:需要一個緯度表,里面有僅僅username的唯一標示,因為hive中不存在自增id

select distinct 
    price,
    row_number() over (order by price)
from
    products
order by 
    price;
price  | row_number
---------+------------
  300.00 |          1
  300.00 |          2
  400.00 |          3
  500.00 |          4
  600.00 |          5
  600.00 |          6
  700.00 |          7
  800.00 |          8
  800.00 |          9
  900.00 |         10
 1100.00 |         11

需求同上,如果需要去重的話(distinct)

with prices as (
    select distinct
        price
    from 
        products
)
select price,row_numer()over(order by price) from prices;
price  | row_number
---------+------------
  300.00 |          1
  400.00 |          2
  500.00 |          3
  600.00 |          4
  700.00 |          5
  800.00 |          6
  900.00 |          7
 1100.00 |          8

mysql

因為不能使用這個關鍵字,所以配合其他關鍵字使用

預期效果

Image [3]Image [4]

select deptid,salary
from employee a
where 2 > (
select count(1)
from employee b
where a.salary<b.salary and a.deptid=b.deptid
)
order by a.deptid,a.salary desc;

但是有弊端,如果最大值有多個,那么就會出現多個最大值,so,要動態的

SET @row=0;
SET @groupid='';
select a.deptid,a.salary
from
(
select deptid,salary,case when @groupid=deptid then @row:=@row+1 else @row:=1 end rownum,@groupid:=deptid from employee
order by deptid,salary desc
)a
where a.rownum<=2;

mysql還有其他寫法,通過求出極值再進行關聯

SELECT t.stuid,  
        t.stuname,  
        t.score,  
        t.classid  
FROM stugrade t  
where t.score = (SELECT max(tmp.score) from stugrade tmp where tmp.classid=t.classid)





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM