阿里云大数据利器Maxcompute学习之--窗口函数实现分组TopN

news/2024/9/3 0:30:19 标签: 大数据

看到很多用户经常会问如何对分组内进行排序。
官方文档:https://help.aliyun.com/document_detail/34994.html?spm=5176.doc27891.6.611.Q1bk3j
例如需求:

  1. odps 里面能否做排名操作,比如一个表里面有 用户ID 和 金额 两个字段,用金额大小排序的话,我如何计算用户的排名(金额最大的是 第一名 ,以此类推)
  2. 计算每个金融产品的最大投资者,或者前几名

类似这一类的需求,我们总结为实现分组内的排序,取TopN,那么在hive中有两个个函数可以分开实现
first_value: 取分组内排序后,截止到当前行,第一个值,
row_number():实现组内排序,并对组内行进行标记行号。
那在odps中没有first_value这个函数,但是同样可以实现top1的需求。下面用一个大家最爱的公司员工表来举例实现

员工表:

empnoenamejobmgrhiredatesalcommdeptno
7839KINGPRESIDENTNULL1981-11-17 00:00:005000.0NULL10
7566JONESMANAGER78391981-04-02 00:00:002975.0NULL20
7698BLAKEMANAGER78391981-05-01 00:00:002850.0NULL30
7788SCOTTANALYST75661987-07-13 01:00:003000.0NULL20
7782CLARKMANAGER78391981-06-09 00:00:002450.0NULL10
7369SMITHCLERK79021980-12-17 00:00:00800.0NULL20
7902FORDANALYST75661981-12-03 00:00:003000.0NULL20
7876ADAMSCLERK77881987-07-13 01:00:001100.0NULL20
7900JAMESCLERK76981981-12-03 00:00:00950.0NULL30
7934MILLERCLERK77821982-01-23 00:00:001300.0NULL10
7499ALLENSALESMAN76981981-02-20 00:00:001600.0300.030
7654MARTINSALESMAN76981981-09-28 00:00:001250.01400.030
7844TURNERSALESMAN76981981-09-08 00:00:001500.00.030
7521WARDSALESMAN76981981-02-22 00:00:001250.0500.030

使用row_number()对相同 job 的薪水sal 进行

排序,取组内最大,等不及了,直接上sql

select * from (
    select job,sal,
     row_number() over(partition by job order by sal desc) as rn  from emp
 ) a where rn=1;
//partition by 跟分组字段
//order by 跟排序字段+升降关键字 默认升序排列。

结果:

jobsalrn
ANALYST3000.01
CLERK1300.01
MANAGER2975.01
PRESIDENT5000.01
SALESMAN1600.01

同理如果想实现topN,那把rn=1改成rn

select * from (

select job,ename,sal,
 row_number() over(partition by job order by sal desc) as rn  from emp

) a where rn<3;

结果:

jobenamesalrn
ANALYSTSCOTT3000.01
ANALYSTFORD3000.02
CLERKMILLER1300.01
CLERKADAMS1100.02
MANAGERJONES2975.01
MANAGERBLAKE2850.02
PRESIDENTKING5000.01
SALESMANALLEN1600.01
SALESMANTURNER1500.02

那这是一个简单的例子。
对于类似需求可以用这个方法来实现TopN的计算。
注意:这种方法对于数量级不是很大的或者分组比较均匀的大数据量实用,
如果分组键值不均匀,导致单个或者几个键值比较大,那会有数据倾斜的问题。此时我们可以从sql上优化写法,例如可以排查哪几个键值比较大单独拉出来一个任务执行。

有对大数据技术感兴趣的,可以加笔者的微信 wx4085116.目前笔者已经从阿里离职,博客不代表阿里立场。笔者开了一个大数据培训班。有兴趣的加我。


http://www.niftyadmin.cn/n/1576321.html

相关文章

redis集群cluster搭建,扩容缩容

为什么80%的码农都做不了架构师&#xff1f;>>> 1. 概要说明 1.1. 概述 本文旨在说明平台部署环境搭建的过程和详细步骤说明&#xff0c;为后面系统部署提供清晰的参考依照。 以下搭建部署的环境&#xff0c;为一个小型的分布式集群环境。满足负载均衡和单点…

epel安装第三方扩展源后,运行yum报错的解决方案

yum安装报错&#xff1a;Cannot retrieve metalink for repository: epel. Please verify its path and try again 解决方法&#xff1a; 一句话&#xff1a;把/etc/yum.repos.d/epel.repo&#xff0c;文件baseurl的注释放开&#xff0c;mirrorlist注释掉。 具体如下&#xff1…

标准C++中的String类的使用

要使用标准C中的String类&#xff0c;必须包含#include<string>&#xff08;注意不是<string.h>带.h的是C语言中的头文件&#xff09; 作者&#xff1a;耑新新&#xff0c;发布于 博客园 转载请注明出处&#xff0c;欢迎邮件交流&#xff1a;zhuanxinxinfoxmail…

Netty学习之旅------高仿Dubbo服务调用模型、私有协议实现、编码解码器使用实践

request.setContentLength(contentLength); //这里&#xff0c;其实上层应用不需要知道请求包的长度&#xff0c;这里属于多于的操作 LogUtils.log(“RequestFrameDecoder 成功从服务端响应中解析出业务包,requestId:%d”, requestId); } else if (requestType 2) { // 此处…

where(泛型类型约束)

定义&#xff1a;在定义泛型的时候&#xff0c;我们可以使用 where 限制参数的范围。 使用&#xff1a;在使用泛型的时候&#xff0c;你必须尊守 where 限制参数的范围&#xff0c;否则编译不会通过。 // .NET支持的类型参数约束 &#xff1a; //where T : struct | T必须是一个…

【Java架构师面试题】设计模式面试专题,java线程安全面试

3、什么是对象粒度&#xff1f; 对象中方法的多少就是粒度 4、基本的Java编程设计应遵循的规则&#xff1f; 面向接口编程&#xff0c;优先使用对象组合 5、设计模式的应用范围 所能解决的特定的一类问题中 6、简述什么是单例模式&#xff0c;以及他解决的问题&#xff0c;应…

【微服务框架】SpringCloud之最全篇,java并发编程电子书

当然这个只是个题外话。 Spring Cloud 的版本号并不是我们通常见的数字版本号&#xff0c;而是一些很奇怪的单词。这些单词均为英国伦敦地铁站的站名。同时根据字母表的顺序来对应版本时间顺序&#xff0c;比如&#xff1a;最早 的 Release 版本 Angel&#xff0c;第二个 Rele…

移动前端调试工具-Weinre真机调试

之前做移动前端调试页面的时候就是简单的使用Chrome模拟器调试&#xff0c;能满足基本基本的需求&#xff0c;后来发现了基于Web Inspector(Webkit)的远程调试工具Weinre&#xff0c;可以在PC端直接调试运行在移动设备上的远程页面&#xff0c;&#xff0c;在PC端可以即时修改目…