Bootstrap

Hive窗口函数详解——及3套案例

一,前言

要先了解窗口函数的结构,over()才是窗口函数,而avg()、sum()、max()、min()等是与over()搭配的分析函数

二,常用函数分析

order by是排序的意思,是该窗口中的

partition by可理解为group by 分组。
over(partition by 列名)搭配分析函数时,分析函数按照每一组每一组的数据进行计算的。

rows between 开始位置 and 结束位置 是指定窗口范围,比如第一行到当前行。而这个范围是随着数据变化的。
over(rows between 开始位置 and 结束位置)搭配分析函数时,分析函数按照这个范围进行计算的。

窗口范围说明:
我们常使用的窗口范围是rows between unbounded preceding and current row(表示从起点到当前行),常用该窗口来计算累加。

preceding:往前
following:往后
current row:当前行
unbounded preceding 表示该窗口最前面的行(起点)
unbounded following:表示该窗口最后面的行(终点)
比如说:
rows between unbounded preceding and current row (表示从起点到当前行)
rows between 2 preceding and 1 following(表示往前2行到往后1行)
rows between 2 preceding and 1 current row (表示往前2行到当前行)
rows between current row and unbounded following(表示当前行到终点)

聚合类
avg()、sum()、max()、min()

排名类
row_number()
按照值排序时产生一个自增编号,不会重复(如:1、2、3、4、5、6)
rank()
按照值排序时产生一个自增编号,值相等时会重复,会产生空位(如:1、2、3、3、3、6)
dense_rank()
按照值排序时产生一个自增编号,值相等时会重复,不会产生空位(如:1、2、3、3、3、4)

其他类
lag(列名,往前的行数,[行数为null时的默认值,不指定为null]),可以计算用户上次购买时间,或者用户下次购买时间。

lead(列名,往后的行数,[行数为null时的默认值,不指定为null])

ntile(n)把有序的数据集合平均到指定数量的桶中,将桶号分配给每一行,如果不能平均分配,则优先分配较小编号的桶,并且各桶中能放的行数最多相差1

三,窗口函数练习

第一套:

需求

1、使用 over() 函数进行数据统计, 统计每个用户及表中数据的总数
2、求用户明细并统计每天的用户总数
3、计算从第一天到现在的所有 score 大于80分的用户总数
4、计算每个用户到当前日期分数大于80的天数

数据

20191020,11111,85
20191020,22222,83
20191020,33333,86
20191021,11111,87
20191021,22222,65
20191021,33333,98
20191022,11111,67
20191022,22222,34
20191022,33333,88
20191023,11111,99
20191023,22222,33

建表并导入数据

create table test_window
(logday string,    #logday时间
userid string, 
score int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

#加载数据
load data local inpath '/home/xiaowangzi/hive_test_data/test_window.txt' into table test_window;

先查看表中数据

select  *  from test_window;

在这里插入图片描述

1、使用 over() 函数进行数据统计, 统计每个用户及表中数据的总数

select *, count(userid) over() as total  from  test_window;

在这里插入图片描述

2、求用户明细并统计每天的用户总数

select  *,count(userid) over(partition by logday) as day_total from  test_window;

在这里插入图片描述

3、计算从第一天到现在的所有 score 大于80分的用户总数

select  *,count(userid) over(order by logday rows between unbounded preceding and current row) as total 
from  test_window
where score > 80;

在这里插入图片描述

4、计算每个用户到当前日期分数大于80的天数

select *,
count(userid) over(partition  by userid order by logday rows between unbounded preceding and current row) as total
from test_window
where score > 80  order by logday, userid;

在这里插入图片描述

第二套

需求

1、查询在2017年4月份购买过的顾客及总人数
2、查询顾客的购买明细及月购买总额
3、查询顾客的购买明细及到目前为止每个顾客购买总金额
4、查询顾客上次的购买时间----lag()over()偏移量分析函数的运用
5、查询前20%时间的订单信息

数据

jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94

建表并加载数据

create table business
(
name string, 
orderdate string,
cost int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

#加载数据
load  data local inpath "/home/xiaowangzi/hive_test_data/business.txt" into table business;

查看表数据

select   *  from  business;

在这里插入图片描述

1、查询在2017年4月份购买过的顾客及总人数

select   *,count(name) over() as total  from  business 
where substr(orderdate,1,7) = '2017-04';

在这里插入图片描述

2、查询顾客的购买明细及月购买总额

select 
*,
sum(cost) over(partition by name,substr(orderdate,1,7)) total_amount
from 
business;

在这里插入图片描述

3、查询顾客的购买明细及到目前为止每个顾客购买总金额
分析:按照顾客分组、日期升序排序、组内每条数据将之前的金额累加

select 
*,
sum(cost) over(partition by name order  by  orderdate 
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) total_amount
from 
business;

在这里插入图片描述
4、查询顾客上次的购买时间----lag()over()偏移量分析函数的运用

select 
name,
orderdate,
cost,
lag(orderdate,1) over(partition by name order by orderdate) last_date
from 
business;

在这里插入图片描述

5、查询前20%时间的订单信息

select *  
from 
(select *,
ntile(5) over(order  by  cost) sortgroup_num from  business)t 
where t.sortgroup_num = 1;

在这里插入图片描述

第三套

需求

1、每门学科学生成绩排名(是否并列排名、空位排名三种实现)
2、每门学科成绩排名top n的学生

数据

name    subject score
孙悟空 语文  87
孙悟空 数学  95
孙悟空 英语  68
大海  语文  94
大海  数学  56
大海  英语  84
宋宋  语文  64
宋宋  数学  86
宋宋  英语  84
婷婷  语文  65
婷婷  数学  85
婷婷  英语  78

建表并加载数据

create table score
(
name string,
subject string, 
score int
) row format delimited fields terminated by "\t";

#加载数据
load data local inpath '/home/xiaowangzi/hive_test_data/score.txt' into table score;

在这里插入图片描述

1、每门学科学生成绩排名(是否并列排名、空位排名三种实现)

select  *,
row_number()over(partition by subject order by score desc),
rank()over(partition by subject order by score desc),
dense_rank()over(partition by subject order by score desc)
from score

在这里插入图片描述

2、每门学科成绩排名top n的学生

select *
from 
(select *,row_number() over(partition by subject order by score desc) rmp from score) t
where t.rmp<=3;

在这里插入图片描述

;