项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

hive中的窗口函数,功能非常强大,使用也比较方便,可以给我们的查询提供相当多的遍历。下面就结合具体的需求与实例,一一为大家讲解窗口函数的使用方法。

1.数据准备

先在hive数据库中建一张表,表的结构如下:

hive (tmp)> desc phone_test;
OK
calling_num             string
called_num              string

准备测试文件:

vim phone
130,131
130,131
130,131
130,131
130,131
130,131
130,132
130,132
130,133
130,133
130,134
132,130
132,130
132,130
132,130
132,130
132,131
132,131
132,131
132,133
132,133
132,133
134,135
134,135
134,135
134,135
134,136
134,136
134,136
138,137
138,137
138,137
138,136
138,136
135,130
135,130
135,130
135,130
135,132
135,132

将文件put到hdfs中hive表对应的位置:

hadoop fs -put phone /data/hive/warehouse/tmp.db/phone_test

至此,数据准备工作完毕。

2.row_num()方法,最有用的窗口函数,或许没有之一

表phone_test的第一列为主叫电话,第二列为被叫电话,我们经常有这种需求:对于同一主叫电话,按通话次数的多少(即被叫电话)进行排序。这个时候row_num()方法就派上了用场。请看:

select a.calling_num,called_num,count,
row_number() OVER (distribute BY calling_num sort BY count DESC) rn
from
(select calling_num,called_num,count(*) as count
from phone_test group by calling_num,called_num)a130    131 6   1
130 133 2   2
130 132 2   3
130 134 1   4
132 130 5   1
132 133 3   2
132 131 3   3
134 135 4   1
134 136 3   2
138 137 3   1
138 136 2   2
135 130 4   1
135 132 2   2

最后一列,就是在同一主叫电话中,被叫电话与主叫电话通话次数的排序。怎么样,很方便吧。
如果要取通话最多的那个,在此基础上稍作改动:

select b.calling_num,called_num,count
from
(select a.calling_num,called_num,count,
row_number() OVER (distribute BY calling_num sort BY count DESC) rn
from
(select calling_num,called_num,count(*) as count
from phone_test group by calling_num,called_num)a)b
where b.rn = 1130  131 6
132 130 5
134 135 4
138 137 3
135 130 4

这样就把每组中rn=1的那一行给选了出来。

换一种写法,还可以这么写:

select b.calling_num,called_num,count
from
(select a.calling_num,called_num,count,
row_number() OVER (partition BY calling_num order BY count DESC) rn
from
(select calling_num,called_num,count(*) as count
from phone_test group by calling_num,called_num)a)b
where b.rn = 1130  131 6
132 130 5
134 135 4
138 137 3
135 130 4

效果与前面是一样一样滴!

3.rank() dense_rank()

rank,顾名思义,就是排序啦。这个比排序更高级一点的是,返回的数据项是在分组中的排名,排名相等的会在名词中留下对应的空位。而dense_rank与rank唯一的不同,就是排名相等的时候不会留下对应的空位。
看例子:

select a.calling_num,called_num,count,
rank() over (partition by calling_num order by count desc) rank,
dense_rank() over (partition by calling_num order by count desc) drank,
row_number() OVER (distribute BY calling_num sort BY count DESC) rn
from
(select calling_num,called_num,count(*) as count
from phone_test group by calling_num,called_num)a对应结果的列为:calling_num called_num count rank drank rn
130 131 6   1   1   1
130 133 2   2   2   2
130 132 2   2   2   3
130 134 1   4   3   4
132 130 5   1   1   1
132 133 3   2   2   2
132 131 3   2   2   3
134 135 4   1   1   1
134 136 3   2   2   2
138 137 3   1   1   1
138 136 2   2   2   2
135 130 4   1   1   1
135 132 2   2   2   2

聪明的你,是不是已经明白这两个函数的用法了?

4.ntile()

ntile是按层次查询。其作用是将数据分成几部分,例如我们想把数据总共分为十份,我们想取前10%来做分析。请看:

select calling_num,called_num,count(*),ntile(5) over(order by count(*) desc) til
from phone_test group by calling_num,called_num
130 131 6   1
132 130 5   1
135 130 4   1
134 135 4   2
138 137 3   2
132 133 3   2
132 131 3   3
134 136 3   3
138 136 2   3
130 132 2   4
135 132 2   4
130 133 2   5
130 134 1   5

我们先将所有数据分为了5部分。如果只想查看其中某一部分:

select a.calling_num,a.called_num,count,til from
(select calling_num,called_num,count(*) count,ntile(5) over(order by count(*) desc) til
from phone_test group by calling_num,called_num)a
where til = 1130   131 6   1
132 130 5   1
135 130 4   1

5.一定范围内的聚合

实际应用场景中,我们有各种数据聚合的要求,而且还比一般的计算要复杂。例如对与电商来说,经常需要看当月与今年之前所有月的累计订单量。对于销售人员来说,也经常需要看当月与今年之前或这个季度之前的累计销售额。对于本文中的例子,我们想计算当前号码的通话总和,以及与之前所有号码通话总和的累计:

select calling_num,sum(num),
sum(sum(num)) over(order by calling_num ROWS between unbounded preceding and current row) as cumulative_sum
from
(select calling_num,called_num,count(*) as num
from phone_test group by calling_num,called_num)a
group by calling_num130 11  11
132 11  22
134 7   29
135 6   35
138 5   40

sum(sum(num))这种写法中,里面的sum(num)表示需要累加的和。
重点看下over里面的内容:
order by calling_num表示按主叫电话排序
ROWS between unbounded preceding and current row 肯定就是表示聚合的起始位置与终止位置了。unbounded preceding是起点,表示从第一行开始;current row为默认值,表示到当前行。
以下写法,能达到同样的效果:

select calling_num,sum(num),
sum( sum(num)) over(order by calling_num ROWS unbounded preceding) as cumulative_sum
from
(select calling_num,called_num,count(*) as num
from phone_test group by calling_num,called_num)a
group by calling_num130 11  11
132 11  22
134 7   29
135 6   35
138 5   40

如果只想在当前行对前两行聚合,总共计算前两行+当前行=3行的值,可以这样写:

select calling_num,sum(num),
sum( sum(num)) over(order by calling_num ROWS between 2 preceding and current row) as cumulative_sum
from
(select calling_num,called_num,count(*) as num
from phone_test group by calling_num,called_num)a
group by calling_num130 11  11
132 11  22
134 7   29
135 6   24
138 5   18

也可以这么写:

select calling_num,sum(num),
sum( sum(num)) over(order by calling_num ROWS 2 preceding) as cumulative_sum
from
(select calling_num,called_num,count(*) as num
from phone_test group by calling_num,called_num)a
group by calling_num130 11  11
132 11  22
134 7   29
135 6   24
138 5   18

如果想对之前一行后面一行进行聚合,总共前面一行+当前行+后面一行=3行计算结果,可以这么写:

select calling_num,sum(num),
sum(sum(num)) over(order by calling_num ROWS between 1 preceding and 1 following) as cumulative_sum
from
(select calling_num,called_num,count(*) as num
from phone_test group by calling_num,called_num)a
group by calling_num130 11  22
132 11  29
134 7   24
135 6   18
138 5   11

hive 窗口函数 应用场景与实战详解相关推荐

  1. 《Unity 4 3D开发实战详解》一6.7 物理引擎综合案例

    本节书摘来异步社区<Unity 4 3D开发实战详解>一书中的第6章,第6.7节,作者: 吴亚峰 , 杜化美 , 张月霞 , 索依娜 责编: 张涛,更多章节内容可以访问云栖社区" ...

  2. flutter 获取android 还是ios_Flutter完整开发实战详解(二十、 Android PlatformView 和键盘问题)...

    作为系列文章的第二十篇,本篇将结合官方的技术文档科普 Android 上 PlatformView 的实现逻辑,并且解释为什么在 Android 上 PlatformView 的键盘总是有问题. 为什 ...

  3. 视频教程-HTML5+CSS3项目实战详解-HTML5/CSS

    HTML5+CSS3项目实战详解 13年软件开发经验,设计开发30多个大型软件,涉及政府.银行.电信.能源等大型软件项目. 精通J2EE体系架构,熟练使用Struts.Spring.hibernate ...

  4. 《Android多媒体应用开发实战详解:图像、音频、视频、2D和3D》——2.1节简析Android安装文件...

    本节书摘来自异步社区<Android多媒体应用开发实战详解:图像.音频.视频.2D和3D>一书中的第2章,第2.1节简析Android安装文件,作者 王石磊 , 吴峥,更多章节内容可以访问 ...

  5. 《Android 网络开发与应用实战详解》——2.1节简析Android安装文件

    本节书摘来自异步社区<Android 网络开发与应用实战详解>一书中的第2章,第2.1节简析Android安装文件,作者 王东华,更多章节内容可以访问云栖社区"异步社区" ...

  6. 第10课:底实战详解使用Java开发Spark程序学习笔记

    第10课:底实战详解使用Java开发Spark程序学习笔记 本期内容: 1. 为什么要使用Java? 2. 使用Java开发Spark实战 3. 使用Java开发Spark的Local和Cluster ...

  7. 第8课:彻底实战详解使用IDE开发Spark程序

    第8课:彻底实战详解使用IDE开发Spark程序 1.下载安装windows下的scala-2.10.4. 2.打开eclipse,新建scala project: WordCount 3.修改依赖的 ...

  8. 第8课:彻底实战详解使用IDE开发Spark程序--集群模式运行

    第8课:彻底实战详解使用IDE开发Spark程序--集群模式运行 拷贝WordCount.scala生成WordCountCluster.scala. 1. 将object WordCount改为ob ...

  9. 【华为云计算产品系列】eBackup云备份原理及实战详解

    [华为云计算产品系列]eBackup云备份原理及实战详解 1. 基础概念 2. eBackup的组网方式 2.1. LAN-Base 2.2. LAN-Free 2.3. Server-Free 3. ...

  10. Flutter完整开发实战详解(十七、 实用技巧与填坑二)

    作为系列文章的第十七篇,本篇再一次带来 Flutter 开发过程中的实用技巧,让你继续弯道超车,全篇均为个人的日常干货总结,以实用填坑为主,让你少走弯路狂飙车. Flutter 完整实战实战系列文章专 ...

最新文章

  1. 邮件发送类,支持HTML格式,支持优先级设置
  2. 智能POS常见问题整理
  3. 复杂系统是如何挂掉的
  4. 蓝桥杯练习系统 —— 题解目录
  5. 3D游戏的照明设计理论,第4部分:如何在游戏引擎中照亮游戏世界
  6. Spring Cloud Alibaba基础教程:与Dubbo的完美融合
  7. java 参数类型不确定_java泛型的那些事
  8. windows 2013 datacenter 安装sql server2008 r2兼容性
  9. jvm gc监控分析常用命令
  10. 通信产业2017走向后摩尔时代
  11. 重读模电教材一_童诗白、华成英
  12. 在线工具 将图片透明化
  13. tan和cot的梗_“sin对cos说 我们今晚是tan呢?还是cot呢?”啥意思
  14. 华为机试真题 C++ 实现【竖直四子棋】
  15. 一次安装IE11浏览器的经历
  16. 主流各云平台主机性能对比
  17. 郭敬明:7亿级产品经理的五大绝招
  18. 蓝桥杯:互质数及其定义
  19. logrotate 详解
  20. Go语言:模拟鼠标操作(go-vgo/robotgo)

热门文章

  1. vue全局组件中再创建多个组件
  2. Android - Android Studio 自动(auto)添加import 语句
  3. redis延时双删保证和数据库的一致性
  4. redis 8种淘汰策略
  5. Git ssh_key生成方法
  6. java 计算两个日期之间的自然周
  7. hibernate必须知道的知识
  8. oracle11g导入导出
  9. Linux部分命令使用说明
  10. 排序构造 GYM 101149 F - The Weakest Sith