一、业务背景
业务上需要通过对二级类目的聚合,输出每个类目下排名30天销量排名TOP100的商品信息。抽象到SQL层面就是:通过对X字段的分组,获取每个分组前N条数据。
二、原始方案
说实话,这个方法有些low,但起码能实现功能。使用存储过程,思路如下:
1.创建一张临时表先放着:create temp_top_by_catename2
2.查询所有的二级类目: select distict cate_level2_name from xxx where ds=max_pt('xxx')
3.将cate_level2_name存储在变量数组中catename[];
4.游标遍历catename[];select * from xxx as a where a.cate_level2_name=catename order by sales_count_30 desc limit 100
将每个二级类目的查询结果insert到temp_top_by_catename2表
方案缺点:
(1)时间成本太高,因为有多少个catename分组,就要查询N次表,更改插入N次表。跑了30小时才插了<100个类目分组
(2)另外表基数量很大,每次查询计划的cost值很高。
(3)如果SQL有中断,数据的完整性很难保证
三、优化方案
基于上述方案的种种不爽,问自己一个问题,能否一条语句可以解决Group+Order+topN输出?于是开始了度娘之旅,但都是些嵌套+子查询的方式曲线救国,并达不到想要的效果。在试,从ODPS的函数着手,翻了一遍返现只有一个神奇API貌似像,名字给出:“row_num”.先普及下这个函数的定义:
语法:row_number() over (partition by 分组字段 order by 排序字段 desc ) as topNum
拆解:
(1)partition by :按照某一字段进行分组
(2)order by:分组之后按照该字段进行升序或降序排列
(3)topNum:自定义的名字,就是后面我们要用到的TOPN,同步数据时可设置成变量,动态调整
四、源码
五、性能结果
自此 over,知识有限,大家如有更好的方案欢迎私聊。