Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Hive常用窗口函数实战

Hive常用窗口函数实战

作者头像
Eights
发布于 2020-07-13 06:28:40
发布于 2020-07-13 06:28:40
2.8K00
代码可运行
举报
文章被收录于专栏:Eights做数据Eights做数据
运行总次数:0
代码可运行

本篇文章大概3799字,阅读时间大约10分钟

本文介绍了Hive常见的序列函数,排名函数和窗口函数。结合业务场景展示了Hive分析函数的使用

Hive作为一个分析型的数据仓库组件提供了很多分析函数,熟练使用分析函数可以快速的进行离线业务的开发。

窗口函数属于分析函数,主要用于实现复杂的统计需求。窗口函数和聚合函数的主要区别是:在分组后,窗口函数会返回组内的多行结果而聚合函数一般返回一行结果。

1

over关键字

窗口函数是针对每行数据的窗口,使用over关键字可以进行窗口创建,如果over中没有给定参数,会统计全部结果集。

举个栗子

数据集:销售表

dep_no

部门

series_code

商品类型

code_sales_num

销售数量

业务场景

统计每个部门内每种商品占总销售数量的百分比

如果不使用over关键字,那么第一步应该先计算总数,然后把总数带入hql进行计算,HQL如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
--计算总数 总数为22089,再带入hql中进行计算
select sum(code_sales_num) from lab.dep_sales_detail

--计算商品销售占比
select dep_no, series_code, code_sales_num, 22089 as total_sales_num,
concat(round((code_sales_num / 22089) * 100, 2), '%') as sales_ratio
from lab.dep_sales_detail

这种写法会产生两个job,需要把第一步的结果带入第二步进行计算,比较麻烦

使用over关键字进行开窗操作

over关键字可以清晰的表达统计商品占比的业务逻辑,且只产生了一个job

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select dep_no,
series_code,
code_sales_num,
sum(code_sales_num) over() dep_sales_num ,
concat(round((code_sales_num / sum(code_sales_num) over() * 100), 2), '%') as sales_ratio
from lab.dep_sales_detail

执行结果如下

2

partition by

partition by表示在over执行的窗口中进行分区操作,也就是在进行分区统计

业务场景

统计每个部门内每种商品占该部门总销售数量的百分比

HQL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select dep_no,
series_code,
code_sales_num,
sum(code_sales_num) over(partition by dep_no) dep_sales_num ,
concat(round((code_sales_num / sum(code_sales_num) over(partition by dep_no) * 100), 2), '%') as sales_ratio
from lab.dep_sales_detail

执行结果

这里可以看到partition by子句将dep_no分为了两组,分别统计其总和

3

partition by order by

over(partition by order by)子句,统计的是从分区的第一行到当前行的统计值,可以认为是window函数的特例

业务场景

统计每天每个部门每种商品的累计销售情况 数据集:每日销售表

dep_no

部门编号

series_code

商品类别

sales_date

销售日期

sales_num

销售数量

该业务表达的是按照日期统计累计的销售情况,也就是以每个商品进行分区,从初始行一直累加到当前行的统计值

HQL

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select series_code,
sales_date,
sales_num,
sum(sales_num) over (partition by series_code order by sales_date) as cum_sales
from lab.code_sales_detail

从结果来看,该HQL实现了日期升序下的销售数量累加统计

4

window窗口

partition by order by语法给出了一个从分区首行到当前行的窗口,如果业务需要对窗口进行细粒度划分,则需要使用窗口函数

窗口函数中可以指定窗口大小,下表展示了一个商品从5月1日开始到6月1日的销售情况

  • unbounded preceding指分区的上限——分区的第一行
  • 1 preceding指当前行的上一行
  • 1 following指当前行的下一行
  • unbounded following指分区的下限——分区的最后一行

业务场景

统计每种商品近7天的销售数量

思路:采用一个6 preceding到current row的窗口进行业务统计

HQL

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select series_code,
sales_date,
sales_num,
sum(sales_num) over (partition by series_code order by sales_date rows between 6 preceding and current row) as cum_sales
from lab.code_sales_detail

上述的HQL实现了一种滑动窗口的效果,也就是从分区的顶部开了一个7个元素的窗口在以步长=1的方式往下滑动求和

Tip:以下两个窗口的语义相同

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
-- 窗口1
over (partition by series_code order by sales_date
rows between unbounded preceding and current row)
-- 窗口2
over (partition by series_code order by sales_date)

5

排名函数-TopN求解

对数据集分组求排名的需求非常常见(Top-N)

  • 求取各产品线的销量前三
  • 求取产品各功能模块使用次数前三

Hive可以非常便捷的利用排名函数实现类Top-N的需求。常用的排名函数有以下三个:

函数名

特点

例子

row_number

顺序增加排名

1 2 3 4 5......

rank

相同排名并列且留下顺序空位

1 2 2 4 5......

dense_rank

相同排名并列且顺序增加

1 2 2 3 4......

测试数据:班级 - 学生 - 成绩

按照班级用三种排名函数进行排名,HQL如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select cname, sname, score,
row_number() over (partition by cname order by score desc) as row_number_res,
rank() over (partition by cname order by score desc) as rank_res,
dense_rank() over (partition by cname order by score desc) as dense_rank_res from t2;

查询结果如下

可以看出row_number会一直按照排序顺序走,rank如果存在并列的情况,会进行计数,也就是说rank函数认为并列的记录会进行排名占位。相反,dense_rank认为并列的记录不会占用排名的顺序。

以上三个函数需要根据业务场景灵活使用。

业务场景

统计每个班的前三名,并列名次算作一个名次。

并列算作一个名次则使用dense_rank函数,先排名然后对名次进行过滤即可 HQL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
with q1 as (
select cname, sname, score,
dense_rank() over (partition by cname order by score desc) as rank 
from t2
)
select * from q1
where rank <= 3

查询结果如下:

6

序列函数-物联网状态变化统计分析

Hive中常见的序列函数

lag

当前行上一行数据

lead

当前行下一条数据

first_value

分区窗口内的第一个值

last_value

分区窗口内的最后一个值

ntile

将分组数据按顺序切分

有了之前的分析函数经验,这里不展示每个序列函数的用途,下面以物联网的一个典型场景介绍lead函数的使用。

业务场景

统计物联网控制板上温度控制模块的使用次数(曾经为了实现这个需求,我写了Spark应用去分组按照时间排序,然后遍历数据集。。。

),其中温控模块的关闭状态为0,打开状态为1。统计使用次数,即是统计温控模块的状态从0-1的变化次数。

数据格式:设备ID - 时间戳 - 温控模块状态

统计思路:统计0-1的状态跳变,在当前行获取上一行的status值作为一列并在最后即可,然后通过lag_status = 0 and status = 1即可统计出使用的次数

HQL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select device_id, device_time, status,
lag(status) over(partition by device_id order by device_time) as lag_status 
from temp_status;

完整的统计HQL如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
with q1 as (
select device_id, device_time, status,
lag(status) over(partition by device_id order by device_time) as lag_status
from temp_status
)
select device_id, count(1) as use_num
from q1
where lag_status = 0 and status = 1
group by device_id

执行结果

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Eights做数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Knockout简单用法
    在最近做的一个项目中,页面数据全部通过js ajax调用webapi接口获取,也就是说页面的数据全部使用javascript脚本填充,这就想到了使用一个MVVM模式的js框架来做这件事,在该项目中选择了Knockout.js。下面简单介绍一下Knockout的基本用法,作为备忘。
写代码的猿
2019/04/11
1.4K0
KnockoutJS语法
  假设我们的页面输入区域有一个div用来展示一件物品的名字,同时有一个输入框用来编辑这件物品的名字
javascript.shop
2019/09/04
2.4K0
KnockoutJS语法
MVC3.0+knockout.js+Ajax 实现简单的增删改查
    自从到北京入职以来就再也没有接触MVC,很多都已经淡忘了,最近一直在看knockout.js 和webAPI,本来打算采用MVC+knockout.js+webAPI来实现这个小DEMO的,无奈公司用的开发环境是VS2010只安装了MVC3.0。那就先练习一下MVC和knockout吧。博客园里有很多这样的文章,但是觉得还是要自己亲自动手写一下。
写代码的猿
2019/04/11
2.5K0
MVC3.0+knockout.js+Ajax 实现简单的增删改查
Knockout.Js官网学习(监控属性Observables)
  现在已经知道如何创建一个简单的view model并且通过binding显示它的属性了。但是KO一个重要的功能是当你的view model改变的时候能自动更新你的界面。当你的view model部分改变的时候KO是如何知道的呢?答案是:你需要将你的model属性声明成observable的, 因为它是非常特殊的JavaScript objects,能够通知订阅者它的改变以及自动探测到相关的依赖。
aehyok
2018/09/11
1.5K0
Knockout.Js官网学习(监控属性Observables)
Knockout.Js官网学习(checked 绑定)
checked绑定是关联到checkable的form表单控件到view model上 - 例如checkbox(<input type='checkbox'>)或者radio button(<input type='radio'>) 。当用户check关联的form表单控件的时候,view model对应的值也会自动更新,相反,如果view model的值改变了,那控件元素的check/uncheck状态也会跟着改变。
aehyok
2018/09/11
2.2K0
Knockout.Js官网学习(checked 绑定)
Knockout.Js官网学习(visible绑定)
让visible绑定到DOM元素上,使得该元素的hidden或visible取决于绑定的值。
aehyok
2018/09/11
1.7K0
Knockout.Js官网学习(style绑定、attr绑定)
style绑定是添加或删除一个或多个DOM元素上的style值。比如当数字变成负数时高亮显示,或者根据数字显示对应宽度的Bar。(注:如果你不是应用style值而是应用CSS class的话,请参考CSS绑定。)
aehyok
2018/09/11
4.1K0
Knockout.Js官网学习(style绑定、attr绑定)
Knockout.Js官网学习(简介)
最近一段时间在网上经常看到关于Knockout.js文章,于是自己就到官网看了下,不过是英文的,自己果断搞不来,借用google翻译了一下。然后刚刚发现在建立asp.net mvc4.0的应用程序的时候,建完之后我直接在项目的Scripts中看到了
aehyok
2018/09/11
2.4K0
Knockout.Js官网学习(简介)
Knockout.Js官网学习(text绑定)
text 绑定到DOM元素上,使得该元素显示的文本值为你绑定的参数。该绑定在显示<span>或者<em>上非常有用,但是你可以用在任何元素上。
aehyok
2018/09/11
2.2K0
Knockout.Js官网学习(click绑定)
click绑定在DOM元素上添加事件句柄以便元素被点击的时候执行定义的JavaScript 函数。大部分是用在button,input和连接a上,但是可以在任意元素上使用。
aehyok
2018/09/11
3.1K0
Knockout.Js官网学习(click绑定)
Knockout.Js官网学习(options绑定)
options绑定控制什么样的options在drop-down列表里(例如:<select>)或者 multi-select 列表里 (例如:<select size='6'>)显示。此绑定不能用于<select>之外的元素。关联的数据应是数组(或者是observable数组),<select>会遍历显示数组里的所有的项。
aehyok
2018/09/11
1.8K0
Knockout.Js官网学习(options绑定)
Knockout.Js官网学习(value绑定)
value绑定是关联DOM元素的值到view model的属性上。主要是用在表单控件<input>,<select>和<textarea>上。
aehyok
2018/09/11
2.3K0
Knockout.Js官网学习(value绑定)
Knockout.Js官网学习(html绑定、css绑定)
html绑定到DOM元素上,使得该元素显示的HTML值为你绑定的参数。如果在你的view model里声明HTML标记并且render的话,那非常有用。
aehyok
2018/09/11
2.6K0
Knockout.Js官网学习(html绑定、css绑定)
knockoutjs 上自己实现的flux
在knockoutjs 上实现 Flux 单向数据流 状态机,主要解决多个组件之间对数据的耦合问题。 一、其实简单 flux的设计理念和实现方案,很大程度上人借鉴和参考了Vuex的实现,只是简化了某些
sam dragon
2018/01/17
9770
knockoutjs 上自己实现的flux
Knockout.Js官网学习(event绑定、submit绑定)
event绑定在DOM元素上添加指定的事件句柄以便元素被触发的时候执行定义的JavaScript 函数。大部分情况下是用在keypress,mouseover和mouseout上。
aehyok
2018/09/11
2.7K0
Knockout.Js官网学习(event绑定、submit绑定)
Knockout.Js官网学习(enable绑定、disable绑定)
enable绑定使DOM元素只有在参数值为 true的时候才enabled。在form表单元素input,select,和textarea上非常有用。
aehyok
2018/09/11
2.3K0
Knockout.Js官网学习(enable绑定、disable绑定)
Knockout.Js官网学习(创建自定义绑定)
你可以创建自己的自定义绑定 – 没有必要非要使用内嵌的绑定(像click,value等)。你可以你封装复杂的逻辑或行为,自定义很容易使用和重用的绑定。例如,你可以在form表单里自定义像grid,tabset等这样的绑定。
aehyok
2018/09/11
8350
Knockout.Js官网学习(创建自定义绑定)
MVVM(Knockout.js)的新尝试:多个Page,一个ViewModel
对于面向数据的Web应用来说,MVVM模式是一项不错的选择,它借助JS框架提供的“绑定”机制是我们无需过多关注UI(HTML)的细节,只需要操作绑定的数据源。MVVM最早被微软应用于WPF/SL的开发,所以针对Web的MVVM框架来说,Knockout.js(以下简称KO)无疑是“根正苗红”。在进行基于KO的Web应用开发时,我们一般会为具体的Web页面定义针对性的ViewModel,但是在很多情况下很多页面具有相同的UI结构和操作行为,考虑到重用和封装,我们是否为它们创建一个共享的ViewModel呢。最
蒋金楠
2018/01/15
2.9K0
MVVM(Knockout.js)的新尝试:多个Page,一个ViewModel
通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用
较之面向最终消费者的网站,企业级Web应用对用户体验的要求要低一些。不过客户对“用户体验”的要求是“与日俱增”的,很多被“惯坏了”的用户已经不能忍受Postback带来的页面刷新,所以Ajax在企业级Web应用中得到了广泛的应用。企业级Web应用的一个特点是以“数据处理”为主,所以“面向绑定”的Knockout.js 是一个不错的选择。ASP.NET Web API,作为.NET平台最好的REST服务开发平台(主要与WCF相比),则可以以服务的形式提供对数据的后台处理。 一、一个简单的基于CRUD的Web应
蒋金楠
2018/01/15
1.3K0
通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用
在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用
由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET MVC的书籍“额外奉送”的),以至于很多人会觉得ASP.NET Web API仅仅是ASP.NET MVC的一个小小的扩展而已,自身并没有太多“大书特书”的地方。而真实的情况下是:ASP.NET Web API不仅仅具有一个完全独立的消息处理管道,而且这个管道比为ASP.NET MVC设计的管道更为复杂,功能也更
蒋金楠
2018/01/15
4.7K0
在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用
推荐阅读
相关推荐
Knockout简单用法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验