数据分析 -Hive学习 Day5

本文详细介绍了Hive中的窗口函数,包括累计计算、分区排序、切片排序和偏移分析,通过实例展示了如何使用窗口函数进行数据处理,如累计数值计算、移动平均值、排名和切片分组等,适合数据分析人员学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HIVE 核心技能之窗口函数

大家好呀,这节课我们学习 Hive 核心技能中最难的部分——窗口函数。窗口函数我们之前在学 MySQL 的时候有学过一些,但是只学了三个排序的窗口函数。这节课我们会学习更多的窗口函数,包括累计计算、分区排序、切片排序以及偏移分析。

在正式学习之前,我们需要先明确一下窗口函数和GROUP BY分组的区别。二者在功能上有相似之处,但是它们存在本质区别。

1. 分组会改变表的结构,而窗口函数不会改变表的结构。比如原表有10行数据,分成两组后只有两行,而窗口函数仍然返回十行数据。

2. 分组只能查询分组后的字段,包括分组字段(组名)和聚合函数字段。而窗口函数对查询字段没有限制,也就是可以查询原表的任意字段,再加上窗口函数新增的一列值。

好啦,现在让我们一起进入窗口函数的世界吧~

本节课主要内容:

1、累计计算窗口函数

(1)sum(…) over(……)

(2)avg(…) over(……)

(3)语法总结

2、分区排序窗口函数

(1)row_number()

(2)rank()

(3)dense_rank()

3、切片排序窗口函数

(1)ntile(n) over(……)

4、偏移分析窗口函数

5、重点练习

大家在做报表的时候,经常会遇到计算截止某月的累计数值,通常在EXCEL里可以通过函数来实现。

那么在HiveSQL里,该如何实现这种累计数值的计算呢?那就是利用窗口函数!

关于窗口函数的几点说明:

需求分析 :既然要进行按月累计,我们就先要把2018年的每笔交易时间转换成月并按月分组聚合计算,得出一个2018年每月支付金额总合表,再基于这张表用窗口函数进行累计计算。

2018年每月支付金额总和表:

再用窗口函数进行月度累计:

年度进行汇总。

这个需求比需求1多了一个需求,那就是年度汇总。那我们只需要在上个需求的子查询中加一个 year 字段即可。

说明:

1、over 中的 partition by 起到了窗口内将数据分组的作用。事实上,加上partition by之后,可以理解为分成了多个窗口,并在每个窗口内进行累加计算或者分区。

如果不加 partition by a.year 的话,运行结果就是这样单纯按月份进行分组的:

2、order by 按照什么顺序进行累加,升序ASC、降序DESC,默认是升序。

大家看股票的时候,经常会看到这种K线图,里面经常用到的就是7日、30日移动平均的趋势图,那如何使用窗口函数来计算移动平均值呢?

需求分析 :这个需求要求每个月近三个月的移动平均支付金额,这里我们要用到一个新知识点,在窗口函数 avg over 的 order by a.month 之后加一句 rows between 2 preceding and current row 来设定计算移动平均的范围,这个语句的含义就是包含本行及前两行。其他部分的写法跟前面的需求类似,先取出2018年每个月的支付金额总和,再用窗口函数求移动平均。

注意:

sum(…A…) over(partition by …B… order by …C… rows between …D1… and …D2…)

avg(…A…) over(partition by …B… order by …C… rows between…D1… and …D2…)

A:需要被加工的字段名称

B:分组的字段名称

C:排序的字段名称

D:计算的行数范围

rows between unbounded preceding and current row

——包括本行和之前所有的行

rows between current row and unbounded following

——包括本行和之后所有的行

rows between 3 preceding and current row

——包括本行以内和前三行

rows between 3 preceding and 1 following

——从前三行到下一行(5行)

max(……) over(partition by …… order by …… rows between ……and ……)

min(……) over(partition by …… order by …… rows between ……and ……)

row_number() 、rank()、dense_rank()

用法:这三个函数的作用都是返回相应规则的排序序号

row_number() over(partition by …A… order by …B… )

rank() over(partition by …A… order by …B… )

dense_rank() over(partition by …A… order by …B… )

A:分组的字段名称

B:排序的字段名称

注意: 这3个函数的括号内是不加任何字段名称的!

row_number :它会为查询出来的每一行记录生成一个序号,依次排序且不会重复。

rankdense_rank :在各个分组内, rank() 是跳跃排序,有两个第一名时接下来就是第三名, dense_rank() 是连续排序,有两个第一名时仍然跟着第二名。

实例练习:

再眼熟一下 user_trade 的表结构:

需求分析 :先限定时间范围,然后根据 user_name 进行分组,接着选出 分组去重后的 user_name,并计算每个用户 goods_category 的数量(记得 distinct 去重),再然后就是用窗口函数对 goods_category 的数量进行排序,当然选择哪一种排序方法要看具体要求,这里我们可以三种方法都试一下看看结果:

注意 :窗口函数中的 order by 字段不能用 select 中字段的重命名,因为二者是同时执行的。

需求分析 : 先用窗口函数将2019年每个用户的支付总金额算出来并进行排序,再以此作为子查询,从中取出排名在第10、20、30名的用户名、支付总金额以及排名次序。企业一般会使用 dense_rank 进行排序,所以我们这里直接用 dense_rank。

2019年每个用户的支付总金额排名:

2019年支付金额排名在第10、20、30名的用户:

ntile(n) over(partition by …A… order by …B… )

n:切分的片数

A:分组的字段名称

B:排序的字段名称

需求分析 :这个需求很简单,把需求5第一步的排序窗口函数变成切片即可。注意时间筛选条件变成2019年1月。

需求分析 : 排名前10%,也就是一共分成10组,取第1组。那么我们先切片分组:

然后再取第一组:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值