Hive的窗口函数

时间:2024-10-03 07:30:05

目录

一、窗口函数语法及说明

什么是窗口函数?

常见分析函数:

over()函数

二、hive窗口函数应用案例(1)

1、准备数据(1)

2、函数操作

2.1、聚合型窗口函数的使用[count(...) over()/sum(...) over()/ avg(...) over()/...]

2.2、over()函数中的窗口范围使用

2.3、lag(col,n)、lead(col,n)、ntile(n) 、first_value、last_value分析函数的使用

三、hive窗口函数应用案例(2)

1、准备数据(2)

2、函数操作

2.1、row_number()函数、rank()函数、dense_rank()函数与over()函数合用。

2.2、over()函数中的窗口范围使用


一、窗口函数语法及说明

什么是窗口函数?

窗口函数是用于分析用的一类函数,要理解窗口函数要先从聚合函数说起。 大家都知道聚合函数是将某列中多行的值合并为一行,比如sum、count等。 而窗口函数则可以在本行内做运算,得到多行的结果,即每一行对应一行的值。 通用的窗口函数可以用下面的语法来概括:

分析函数 over([partition by 列名] [order by 列名 [rows between 开始位置 and 结束位置]])

常见分析函数:

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

排名类
row_number() 按照值排序时产生一个自增编号,不会重复
rank() 按照值排序时产生一个自增编号,值相等时会重复,会产生空位
dense_rank() 按照值排序时产生一个自增编号,值相等时会重复,不会产生空位

其他类

lag(列名,往前的行数n,[行数为null时的默认值,不指定为null]) --往前第n行
lead(列名,往后的行数n,[行数为null时的默认值,不指定为null])  --往后第n行
first_value取分组内排序后,截止到当前行,第一个值。 
last_value取分组内排序后,截止到当前行,最后一个值。
ntile(n) 把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,ntile返回此行所属的组的编号

over()函数

over()全局扫描,over(order by col)按照行(字段排序)扫描,over(partition by col)按照分区(组)扫描

COVER() :指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化 -- cover()

over()函数中的窗口范围说明:

current row :当前行 
n percending :往前n行数据 
n following :往后n行数据  
unbounded :起点 
unbounded perceding :表示从前面的起点 
unbounded following :表示到后面的终点 

二、hive窗口函数应用案例(1)

1、准备数据(1)

  1. --数据字段说明:用户名(username),购买日期(buydate),购买价格(buycost)
  2. [hdp@hdp02 demo]$ vi  
  3. 张飞,2019-01-01,10
  4. 关羽,2019-01-02,15
  5. 张飞,2019-02-03,23
  6. 关羽,2019-01-04,29
  7. 张飞,2019-01-05,46
  8. 张飞,2019-04-06,42
  9. 关羽,2019-01-07,50
  10. 张飞,2019-01-08,55
  11. 刘备,2019-04-08,62
  12. 刘备,2019-04-09,68
  13. 诸葛亮,2019-05-10,12
  14. 刘备,2019-04-11,75
  15. 诸葛亮,2019-06-12,80
  16. 刘备,2019-04-13,94
  17. hive > create database demodb03; 
  18. hive > use demodb03; 
  19. hive > create table demo01 (username string,buydate string,buycost string)
  20.  row format delimited fields terminated by ',' lines terminated by '\n';
  21. hive > load data local inpath '/home/hdp/demo/' into table demo01;
  22. hive > select * from demo01 limit 10;

2、函数操作

2.1、聚合型窗口函数的使用[count(...) over()/sum(...) over()/ avg(...) over()/...]

 注意:sum(...)over()、avg(...)over()等窗口函数的使用有特殊要求。
    over中可以写分组、排序,
    但是分组(按组计算)只能用partition by,排序(逐步计算)使用的是order by。
    对单个字段去重用:distinct,他的执行在窗口函数执行之后执行,
    对多字段合并的去重,需要再建立一次新的查询再使用group by。group by在窗口函数之前先执行。

  1. -- 查询购买明细,及合计总购买次数、总购买金额。
  2. select username,buydate,buycost, -- 购买明细
  3. count(*) over() c, --合计购买次数
  4. sum(buycost) over() s -- 合计购买金额
  5. from demo01;
  6. -- 查询购买明细,及每个用户的合计购买金额。
  7. select username,buydate,buycost, -- 购买明细
  8. sum(buycost) over(partition by username) s -- 每个用户的合计购买金额
  9. from demo01;
  10. -- 查询购买明细,及每个用户每个月购买总额。
  11. select username,buydate,buycost, -- 购买明细
  12. sum(buycost) over(partition by username,month(buydate)) s -- 每个用户每个月购买总额
  13. from demo01;
  14. -- 查询购买明细,及按时间升序的累计的购买金额and累计购买次数。
  15. select username,buydate,buycost, -- 购买明细
  16. sum(buycost) over(order by buydate asc) s, -- 累计的购买金额
  17. count(*) over(order by buydate asc) c -- 累计购买次数
  18. from demo01;
  19. -- 查询按月累计的购买金额及累计购买次数。
  20. select distinct substr(buydate,1,7) t,
  21. sum(buycost) over(order by substr(buydate,1,7) asc) s, -- 按月累计的购买金额
  22. count(*) over(order by substr(buydate,1,7) asc) c -- 按月累计购买次数
  23. from demo01;
  24. -- 统计每个用户每月的购买总额,和截止到当月的累计购买总额。
  25. select ,,max() v,max() sv from
  26. (select username,substr(buydate,1,7) d,
  27. sum(buycost) over(partition by username,month(buydate)) v,
  28. sum(buycost) over(partition by username order by month(buydate) asc) sv
  29. from demo01 ) a
  30. group by ,;
  31. -- 查询购买明细,及每个用户按月累计的购买金额and按月累计的购买次数。
  32. select username,buydate,buycost, -- 购买明细
  33. sum(buycost) over(partition by username order by month(buydate) asc) s, -- 每个用户按月累计的购买金额
  34. count(*) over(partition by username order by month(buydate) asc) c --按月累计的购买次数
  35. from demo01;
  36. -- 查询在2019年4月份,购买过产品的顾客及每个顾客购买次数。
  37. select distinct username,
  38. count(*) over(partition by username) as
  39. from demo01 where substr(buydate,1,7)="2019-04";
  40. -- 统计每个用户的总消费额、消费次数、平均消费金额,单次最高消费金额和最低消费金额。
  41. select distinct username,
  42. sum(buycost) over (partition by username),
  43. count(buydate) over (partition by username),
  44.  round(avg(buycost) over (partition by username),2),
  45.  max(buycost) over (partition by username),
  46.  min(buycost) over (partition by username)
  47. from demo01;

2.2、over()函数中的窗口范围使用

over()函数中的窗口范围说明:

current row :当前行 
n percending :往前n行数据 
n following :往后n行数据  
unbounded :起点 
unbounded perceding :表示从前面的起点 
unbounded following :表示到后面的终点 

  1. -- 按照顾客分组、日期升序排序、组内每条数据将之前的金额累加
  2. select username,buydate,buycost, -- 购买明细
  3. sum(buycost) over(partition by username order by buydate rows between unbounded preceding and current row) cumulative_amount
  4. from demo01;
  5. -- 等价于
  6. select username,buydate,buycost, -- 购买明细
  7. sum(buycost) over(partition by username order by buydate) cumulative_amount
  8. from demo01;
  9. -- 按照客户分组,每个客户的合计购买金额
  10. select distinct username,
  11. sum(buycost) over(partition by username order by buydate rows between unbounded preceding and unbounded following) cumulative_amount
  12. from demo01;
  13. -- 等价于
  14. select distinct username,
  15. sum(buycost) over(partition by username) cumulative_amount
  16. from demo01;

2.3、lag(col,n)、lead(col,n)、ntile(n) 、first_value、last_value分析函数的使用

lag(列名,往前的行数n,[行数为null时的默认值,不指定为null]) --往前第n行
lead(列名,往后的行数n,[行数为null时的默认值,不指定为null])  --往后第n行
first_value取分组内排序后,截止到当前行,第一个值。 
last_value取分组内排序后,截止到当前行,最后一个值。
ntile(n) 把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,ntile返回此行所属的组的编号

  1. -- 查询出明细数据,及顾客上次的购买时间
  2. select username,buydate,buycost, -- 购买明细
  3. lag(buydate,1,'起始') over(partition by username order by buydate asc) t
  4. from demo01;
  5. -- 查询出明细数据,及顾客下次的购买时间
  6. select username,buydate,buycost, -- 购买明细
  7. lead(buydate,1,'最后') over(partition by username order by buydate asc) t
  8. from demo01;
  9. -- 查询显示每个用户的第一次购买时间和最后一次购买时间。
  10. select username,
  11. first_value(buydate) over(partition by username order by buydate) first_date,
  12. last_value(buydate) over(partition by username order by buydate) last_date
  13. from demo01;
  14. -- 查询前50%时间的订单信息
  15. select * from
  16. (select username,buydate,buycost, -- 购买明细
  17. ntile(2) over(order by buydate asc) ar --50%分为2个组(25%则分4个组)
  18. from demo01) a where = 1 ;

三、hive窗口函数应用案例(2)

1、准备数据(2)

  1. -- 字段说明:姓名:name ,考试时间:dates,科目:subject,成绩:score
  2. [hdp@hdp02 demo]$ vim
  3. 张三 2019-01-01 语文 77
  4. 张三 2019-01-02 数学 80
  5. 张三 2019-01-03 外语 70
  6. 张三 2019-01-04 物理 55
  7. 张三 2019-01-05 化学 40
  8. 张三 2019-01-06 生物 45
  9. 李四 2019-01-01 语文 89
  10. 李四 2019-01-02 数学 78
  11. 李四 2019-01-03 外语 69
  12. 李四 2019-01-04 物理 45
  13. 李四 2019-01-05 化学 40
  14. 李四 2019-01-06 生物 50
  15. 王五 2019-01-01 语文 90
  16. 王五 2019-01-02 数学 80
  17. 王五 2019-01-03 外语 80
  18. 王五 2019-01-04 物理 59
  19. 王五 2019-01-05 化学 48
  20. 王五 2019-01-06 生物 45
  21. hive> create table demo02(
  22. name string,dates string,subject string,score int
  23. )row format delimited fields terminated by '\t';
  24. hive> load data local inpath '/home/hdp/demo/' into table demo02;
  25. hive> select * from demo02 limit 20;

2、函数操作

2.1、row_number()函数、rank()函数、dense_rank()函数与over()函数合用。

row_number() 按照值排序时产生一个自增编号,不会重复。(常用于排序)
rank() 按照值排序时产生一个自增编号,值相等时会重复,会产生空位。(最常用用于排名)
dense_rank() 按照值排序时产生一个自增编号,值相等时会重复,不会产生空位(常常会用来分组)

  1. -- 使用上述3个函数,对每个学生的各科成绩,进行不同的排名。
  2. select subject, name,score,
  3. rank() over(partition by subject order by score desc) rank,
  4. row_number() over(partition by subject order by score desc) row_number,
  5. dense_rank() over(partition by subject order by score desc) dense_rank
  6. from demo02;

2.2、over()函数中的窗口范围使用

over()函数中的窗口范围说明:

current row :当前行 
n percending :往前n行数据 
n following :往后n行数据  
unbounded :起点 
unbounded perceding :表示从前面的起点 
unbounded following :表示到后面的终点 

  1. -- 求出每个同学的考试明细:姓名、日期、科目、分数、截止到当天的累计分数、截止到最后一天的总分。
  2. -- 测试preceding、following、current row、unbounded函数。
  3. select name ,dates,subject,score,
  4. sum(score) over(partition by name order by dates ) s1,
  5. sum(score) over(partition by name order by dates rows between unbounded preceding and current row) s2, -- s1=s2
  6. sum(score) over(partition by name) s3,
  7. sum(score) over(partition by name order by dates rows between unbounded preceding and unbounded following) s4 -- s3=s4
  8. from demo02;