当前位置:首页 » 编程语言 » hivesql聚合函数
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

hivesql聚合函数

发布时间: 2023-02-24 21:45:47

1. Hivesql核心技能之窗口计算

目标:
1、掌握 sum()、avg()等用于累计计算的聚合函数,学会对行数的限制(移动计算);
2、掌握 row_number(),rank()、dense_rank()用于排序的函数;
3、掌握 ntile()用于分组查询的函数;
4、掌握 lag()、lead()偏移分析函数

窗口函数(window function):
与聚合函数类似,但是窗口函数是每一行数据都生成一个结果,聚合函数可以将多行数据按照规定聚合为一行,一般来说聚合后的行数要少于聚合前的行数,但是有时我们想要既显示聚合前的数据,又要显示聚合后的数据,这时便引入了窗口函数, 窗口函数是在 select 时执行的,位于 order by 之前

在日常工作中,经常遇到 计算截止某月或某天的累计数值 ,在Excel可以通过函数来实现,
在HiveSQL里,可以利用窗口函数实现。

1)2018年每月的支付总额和当年累计支付总额

2)对2017年和2018年公司的支付总额按月度累计进行分析,按年度进行汇总

说明:1、over中的 partition by 起到分组的作用;
2、order by 按照什么顺序进行累加,升序ASC、降序DESC,默认升序
3、正确的分组是非常重要的,partition by 后面的字段是需要累计计算的区域,需要仔细理解

(计算三日留存、七日留存、三十日留存等方式可以使用这个函数。)

3)对2018年每个月的近三个月进行移动的求平均支付金额

用法:这三个函数的作用都是返回相应规则的排序序号,由于排序函数不是二次聚合计算,因此不一定要使用子查询

4)2019年1月,用户购买商品品类数量的排名

5)选出2019年支付金额排名在第10、20、30名的用户

6)将2019年1月的支付用户,按照支付金额分成5组

7)选出2019年退款金额排名前10%的用户

说明:Lag和Lead分析函数可以在同一次查询中取出同一字段的 前N行数据(Lag)和后N行的数据(Lead) 作为独立的列。

在实际应用当中,若要用到取今天和昨天的某字段差值时,Lag和Lead函数的应用就显得尤为重要。
当然,这种操作可以用表的 自连接实现 ,但是Lag和Lead与 left join、 right join等自连接相比,效率更高,SQL语句更简洁。

8)支付时间间隔超过100天的用户数(这一次购买距离下一次购买的时间?,注意datediff函数是日期大的在前面)

9)每个城市,不同性别,2018年支付金额最高的TOP3用户

步骤总结:
1、首先筛选出每个用户和每个用户总的消费金额;
2、对两个表进行连接提取需要的字段;
3、对连接后的表进行二次聚合计算,计算出不同城市、性别的金额排名;
4、对二次聚合计算的表进行条件筛选提取

10)每个手机品牌退款金额前25%的用户

步骤总结:
1、首先筛选出每个用户和每个用户的总退款金额;
2、对两个表进行连接提取需要的字段;
3、对连接后的表进行按手机品牌内分组;
4、对分组后的表进行条件筛选提取

2. hive sql语言问题,怎么按一列聚合第二列的多个值合并成1个值,再按这个值group by

--假设表名为tb
selectys,count(*)
from
(
selectx,to_char(wm_concat(y))ys
fromtb
groupbyx
)w
groupbyys
;

3. 数据分析课程笔记 - 20 - 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 :它会为查询出来的每一行记录生成一个序号,依次排序且不会重复。

rank&dense_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组。那么我们先切片分组:

然后再取第一组:

说明:Lag和Lead分析函数可以在同一次查询中取出同一字段的前N行的数据(Lag)和后N行的数据(Lead)作为独立的列。

在实际应用当中,若要用到取今天和昨天的某字段差值时,Lag和Lead函数的应用就显得尤为重要。当然,这种操作可以用表的自连接实现,但是LAG和LEAD与left join、right join等自连接相比,效率更高,SQL语句更简洁。

lag(exp_str,offset,defval) over(partion by ……order by ……)
lead(exp_str,offset,defval) over(partion by ……order by ……)

lag() 函数示例:

lead() 函数示例:

需求分析: 先要从 user_trade 表中取出每个用户的支付时间,把每个用户放到一个窗口中,按照支付时间进行排序,取出偏移列: lead(dt,1,dt) over(partition by user_name order by dt)。接着基于该子查询,筛选出时间间隔大于100天的用户,并计算数量。

注意 : 如果上面偏移分析函数写成 lead(dt,1,dt) 就不用加后面的 dt is not null 了,因为有默认值的话,间隔就是0,肯定是不满足条件的。

需求分析

第一步 :这个需求要用到 user_trade 和 user_info 两张表,前者取支付时间和金额,后者取城市和性别。先对这两张表基于 user_name 进行左连接,并取出相应字段,用窗口函数进行分组排序:

这一步的运行结果是这样的:

第二步 :基于上述结果取出TOP3:

需求分析:

第一步 :这个需求同样要用到两张表 user_refund 和 user_info。我们先把每个退款用户的退款金额和手机品牌取出来,并用窗口函数进行切片排序,25%就是分成4片:

注意 :这里之所以要加 WHERE dt is not null 是因为 user_refund 是一个分区表,分区表要对分区字段进行限制,否则 hive 会报错。

第二步 :选择前25%,也就是第一片:

最后补充一个从 hive 导出结果数据的命令:

以上就是这节课的全部内容了。做完整个练习,真的半条命都没了。窗口函数果然很难,不过掌握方法、多多练习,学会拆解需求,一步一步来做,就能明显降低难度。希望以后有机会能用到这么复杂的技能,哈哈~!

4. HiveSQL核心技能之常用函数

目标:
1、掌握hive基础语法、常用函数及其组合使用
2、掌握一些基本业务指标的分析思路与实现技巧

1)某次经营活动中,商家发起了“异性拼团购”,试着针对某个地区的用户进行推广,找出匹配用户。

注意:如果该表是一个分区表,则where条件中必须对分区字段进行限制

2)选出在2018年12月31日,购买的商品品类是food的用户名、购买数量、支付金额

3)试着对本公司2019年第一季度商品的热度与价值度进行分析。
"2019年一月到三月,每个品类有多少人购买,累计金额是多少"

GROUP BY ... HAVING(分类汇总过滤)

4)找出在2019年4月支付金额超过5万元的用户,给这些VIP用户赠送优惠券

5)2019年4月,支付金额最多的TOP5用户

查看Hive中的函数:show functions;
查看具体函数的用法:1)desc function 函数名;2)desc function extended函数名;

6)

7)用户的首次激活时间,与2019年5月1日的日期间隔。

datediff(string enddate,string startdate):结束日期减去开始日期的天数

拓展:日期增加函数(增加天数)、减少函数(减少天数) —— date_add、date_sub(类型要是string类型的)
date_add(string startdate,int days)、date_sub(string startdate,int days)

case when 函数

8)统计以下四个年龄段20岁以下、20-30岁、30-40岁、40岁以上的用户数

case when 的时候不用加group by,只有在聚合函数的时候才需要group by

if 函数

9)统计每个性别的用户等级高低分布情况(假设level大于5为高级,注意列名不能使用中文的)

10)分析每个月都拉新情况

substring(stringA,INT start,int len),substr(stringA,INT start,int len),截取起始位置和截取长度

extra1需要解析json字段,然后用$.key取出想要获取的value;
extra2使用的是中括号加引号的方式进行字段提取和分组;
两种写法要看字段类型的不同采取不同的方式

11)求不同手机品牌的用户数

12)ELLA用户的2018年的平均每次支付金额,以及2018年最大的支付日期和最小的支付日期的间隔

13)2018年购买的商品品类在两个以上的用户数

步骤总结:
1、先求出每个人购买的商品品类书
2、筛选出购买商品品类书大于2的用户
3、统计符合条件的用户有多少个

14)用户激活时间在2018年,年龄段在20-30岁和30-40岁的婚姻情况分布

步骤总结:
1、先选出激活时间在2018年的用户,并把他们所在的年龄段计算好,并提取出婚姻状况;
如何select后面没有进行聚合,则可以不用使用group by,直接使用where进行过滤就可以;
2、取出年龄段在20-30岁和30-40岁的用户,把他们的婚姻状况转义成可理解的说明;
3、聚合计算,针对年龄段,婚姻状况的聚合

5. SQL中只要用到聚合函数就一定要用到group by 吗

SQL中只要用到聚合函数就不一定要用到group by。聚合函数是对一组值执行计算,并返回单个值,也被称为组函数。 聚合函数可以应用于SELECT 查询语句的 GROUP BY 子句的HAVING子句中,但不可用于WHERE语句中,因为WHERE是对逐条的行记录进行筛选。

(5)hivesql聚合函数扩展阅读:

Transact-SQL编程语言提供的聚合函数有:

1、AVG:返回指定组中的平均值,空值被忽略。例:select prd_no,avg(qty) from sales group by prd_no.

2、COUNT:返回指定组中项目的数量。例:select count(prd_no) from sales.

3、COUNT_BIG:返回指定组中的项目数量,与COUNT函数不同的是COUNT_BIG返回bigint值,而COUNT返回的是int值。例:select count_big(prd_no) from sales.

4、MIN:返回指定数据的最小值。例:select prd_no,min(qty) from sales group by prd_no.

5、MAX:返回指定数据的最大值。例:select prd_no,max(qty) from sales group by prd_no.