Hive 开窗函数详解

1.开窗函数查询
  •  窗口函数通常是分析人员使用 hive ql 进行一些复杂逻辑计算时使用的特殊函数,其中 over() 通常与聚合函数共同使用,比如 count()、sum()、min()、max()、avg() 等。
  •  over() 具有一定的窗口语义,如:OVER(ROWS ((CURRENT ROW) | (UNBOUNDED) PRECEDING) AND (UNBOUNDED |(CURRENT ROW) ) FOLLOWING )
  •  over() 直接使用时,通常是指定全量数据,当我们想要按某列的不同值进行窗口划分时,可以在 over() 中加入 partition by 语句。
 
hive 常用开窗函数说明
   over():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化
   current row:当前行
   preceding n:往前n行数据
   following n:往后n行数据
   unbounded:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
   lag(col,n):往前第n行数据
   lead(col,n):往后第n行数据
   ntile(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。
 
 

2.Hive  开窗函数代码示例1:

2.1 数据准备:name,orderdate,cost

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
2.2 环境准备
// 创建本地business.txt,导入数据

[luomk@hadoop102 datas]$ vi business.txt


// 创建hive表并导入数据
create table business(
name string,
orderdate string,
cost int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',’;

load data local inpath "/opt/module/datas/business.txt" into table business;
2.3 需求及实现
    • 查询在2017年4月份购买过的顾客及总人数
    • 查询顾客的购买明细及月购买总额
    • 上述的场景,要将cost按照日期进行累加
    • 查询顾客上次的购买时间    • 查询前20%时间的订单信息

// 查询在2017年4月份购买过的顾客及总次数
select name,count(*) over (partition by name)
from business
where substring(orderdate,1,7) = '2017-04’;

// 查询顾客的购买明细及月购买总额
select name,orderdate,cost,sum(cost) over(partition by month(orderdate)) from
business;

// 上述的场景,要将cost按照日期进行累加
select name,orderdate,cost,
sum(cost) over() as sample1,--所有行相加
sum(cost) over(partition by name) as sample2,--按name分组,组内数据相加
sum(cost) over(partition by name order by orderdate) as sample3,--按name分组,组内数据累加
sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4 ,--和sample3一样,由起点到当前行的聚合
sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row) as sample5, --当前行和前面一行做聚合
sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING AND 1 FOLLOWING ) as sample6,--当前行和前边一行及后面一行
sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 --当前行及后面所有行
from business;

// 查看顾客上次的购买时间
select name,orderdate,cost,
lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as time1, lag(orderdate,2) over (partition by name order by orderdate) as time2
from business;


// 查询前20%时间的订单信息
select * from (
    select name,orderdate,cost, ntile(5) over(order by orderdate) sorted
    from business
) t
where sorted = 1;
 
3. Hive  开窗函数代码示例2:

    创建测试表并加载简单的示例数据进行演示

hive> create table recommend.test_window(logday string, userid string, score int)
    > row format delimited
    > Fields terminated by ',’;


logday      userid  score
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
 
示例 1: 简单使用 over() 函数进行数据统计, 统计每个用户及表中数据的总数。
hive> select logday, userid, score, count(*) over()  as total
    > from recommend.test_window;
OK
logday      userid  score total
20191023    22222   33  11
20191023    11111   99  11
20191022    33333   88  11
20191022    22222   34  11
20191022    11111   67  11
20191021    33333   98  11
20191021    22222   65  11
20191021    11111   87  11
20191020    33333   86  11
20191020    22222   83  11
20191020    11111   85  11

//这里使用 over() 与 select count(*) 有相同的作用,好处就是,在需要列出所有列值时不用再进行一次关联。

 

示例 2: 当想要对每天的数据进行统计时,可以使用 partition by 按日期列对数据进行分区处理,如:over(partition by logday)
hive> select logday, userid, count(userid) over(partition by logday) as total
    > from recommend.test_window;
OK
logday      userid  total
20191020    33333   3
20191020    22222   3
20191020    11111   3
20191021    33333   3
20191021    22222   3
20191021    11111   3
20191022    33333   3
20191022    22222   3
20191022    11111   3
20191023    22222   2
20191023    11111   2

// 这种用法与 select logday, count(userid) from recommend.test_window group by logday 具有相同的效果,但是当想要得到 userid 信息时,这种用法的优势就很明显。

 

示例 3: 下面我们想要得到从第一天到现在的所有 score 大于80分的用户总数,此时简单的分区不能满足需求,需要将 order by 和 窗口定义结合使用。
hive>
    > select logday,
    >         count(userid) over(order by logday rows between unbounded preceding and current row)
    > from recommend.test_window
    > where score > 80;
    
OK
20191020    1
20191020    2
20191020    3
20191021    4
20191021    5
20191022    6
20191023    7

//通过 over() 计算出按日期的累加值后,然后去每天的最大值就是需要的总的累加值。

 

示例 4:计算每个用户到当前日期分数大于80的天数。
hive> select userid, logday, score, count(case when score>=80 then userid else null end) over(partition by userid                 order by logday rows between unbounded preceding and current row) as total
    > from recommend.test_window
    > order by logday, userid;
    
useri   logday      score   total
11111   20191020    85  1
22222   20191020    83  1
33333   20191020    86  1
11111   20191021    87  2
22222   20191021    65  1
33333   20191021    98  2
11111   20191022    67  2
22222   20191022    34  1
33333   20191022    88  3
11111   20191023    99  3
22222   20191023    33  1

扩展

  • 分区语句 partition by 除了这里使用的单列分区外,还可以使用多列分区。事实上,这里的分区跟创建 hive 分区表有异曲同工之妙。
  • 窗口的划分除了上面使用的 rows between unbounded preceding and current row 之外,还有其他的使用场景,如:
    ROWS BETWEEN CURRENT ROW AND n FOLLOWING:从当前行到随后的n行  
    ROWS BETWEEN n PRECEDING AND CURRENT ROW:从前n行到当前行  
    ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING: 从当前行到结尾行

     

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值