设为首页 收藏本站
查看: 1222|回复: 0

[经验分享] Hive SQL主要开窗函数用法介绍

[复制链接]
累计签到:5 天
连续签到:1 天
发表于 2018-10-19 10:03:10 | 显示全部楼层 |阅读模式
  在开窗函数出现之前,存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成。为了解决这些问题,在2003年ISO SQL标准加入了开窗函数,开窗函数的使用使得这些经典的难题可以被轻松的解决。
  下面通过一些简单的需求示例介绍主要的开窗函数。
  本例的数据源:
  select * from wx_tmp1;
DSC0000.jpeg

  需求1:要在源表中,增加两列,全国总的gmv和各城市的gmv占比。
  select *,sum(gmv) over() as all_gmv,
  gmv/sum(gmv) over() as gmv_pro
  from wx_tmp1;
DSC0001.jpeg

  这就是开窗函数的妙处。SQL标准允许将所有聚合函数用做开窗函数,只需要在聚合函数后加over()即可。
  over()可以传入对应的子句来达到不同的效果,下面一一介绍。
  需求2:要在源表中,增加两列,各区域的gmv及各分组的gmv。
  select *,
  sum(gmv) over(partition by area) as area_gmv,
  sum(gmv) over(partition by group) as group_gmv
  from wx_tmp1;
DSC0002.jpeg

  partition by对表进行分区然后聚合计算每个分区的数据,且同一个select语句中可以同时使用多个开窗函数,而且这些开窗函数并不会相互干扰。
  需求3:在源表的基础上,增加一列,按gmv升序排列并计算累计gmv。
  select *,
  sum(gmv) over(order by gmv rows between unbounded preceding and current row) as leiji_gmv
  from wx_tmp1;
DSC0003.jpeg

  order by子句可以对结果集按照指定的排序规则进行排序,并且在一个指定的范围内进行聚合运算。
  order by子句的语法为:order by 字段名 range|rows between 边界规则1 and 边界规则2。
  range|rows between 边界规则1 and 边界规则2,这个子句又被称为定位框架。
  range是按照值的范围进行范围的定义,rows是按照行的范围进行范围的定义,边界范围可取值:
  current row:当前行
  n preceding:前N行,比如 2 preceding
  unbounded preceding:一直到第一条记录
  n following:后N行
  unbounded following:一直到最后一条记录
  这个需求中,计算累计gmv,即计算第一条记录到当条记录的gmv之和。
  rows between unbounded preceding and current row,是最常用的定位框架,可以省略。
  因此可以简写为以下:
  select *,
  sum(gmv) over(order by gmv) as leiji_gmv
  from wx_tmp1;
  需求4:在源表中,增加一列,计算gmv的分组排名。
  select *,
  count(city) over(partition by group order by gmv desc) as ranks
  from wx_tmp1;
DSC0004.jpeg

  分组排名有另外三个开窗函数:
  select *,count(city) over(partition by group order by gmv desc) as ranks1,
  rank() over(partition by group order by gmv desc) as ranks2,
  dense_rank() over(partition by group order by gmv desc) as ranks3,
  row_number() over(partition by group order by gmv desc) as ranks4
  from wx_tmp1
DSC0005.jpeg

  通过结果可以看出几种排序的差异。ranks2和ranks3的排序在本例中没有体现:
  ranks2:如果下面还有一个城市的话,排名是11;ranks3:如果下面还有一个城市的话,排名是10。
  需求5:在源表中增加两列,取出每组gmv最大的城市,和最小的城市。
  select *,first_value(city) over(partition by group order by gmv desc) as first_city,
  first_value(city) over(partition by group order by gmv) last_city
  from wx_tmp1
DSC0006.jpeg

  first_value:按分组排序后,取范围内第一个值。相应的还有last_value,按分组排序后,取范围内,最后一个值。
  如果这个需求中,按以下写法的话:
  select *,first_value(city) over(partition by group order by gmv desc) as first_city,
  last_value(city) over(partition by group order by gmv desc) last_city
  from wx_tmp1
  会发现last_city的结果不是我们想要的。是因为使用了默认定义框架:第一行到当前行的最后一个值。
DSC0007.jpeg

  要纠正这个问题,需要使用定位框架,因为相对麻烦,建议用first_value()替代。
  需求6:在源数据中增加两列,第一列取gmv分组排名在当前城市上面1位的城市,第二列取gmv分组排名在当前城市下面1位的城市。
  select *,lag(city,1,null) over(partition by group order by gmv desc) as up_city,
  lead(city,1,null) over(partition by group order by gmv desc) down_city
  from wx_tmp1
DSC0008.jpeg

  如果要取排名前/后两位的城市,调整lag和lead第二个参数即可。第三个参数为默认值,可以省略,省略的话,默认取不到时是NULL,如果不省略的话,取不到时则取指定默认值。
  还有一个开窗函数,如下用法:
  select *,ntile(2) over(partition by group order by gmv desc) rn from wx_tmp1
  即将源表按group分组,并按gmv降序排列后,将每组平均分为2部分。
DSC0009.jpeg

  还有其他聚合函数用法跟sum()一致,就不一一介绍了。
  转自:https://baijiahao.baidu.com/s?id=1592467638440407962&wfr=spider&for=pc


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-623480-1-1.html 上篇帖子: 从SQL数据库中查找指定字符 下篇帖子: Windows Server 2016 路由和远程访问
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表