hive之窗口函数理解与实践

首先,我们要知道什么是窗口子句:

需要指定一个窗口的边界,语法是这样的:

ROWS betweenCURRENT ROW | UNBOUNDED PRECEDING | [num] PRECEDING AND  UNBOUNDED FOLLOWING | [num] FOLLOWING| CURRENT ROW

RANGE between [num] PRECEDING  AND [num]FOLLOWING

如下图:



ROWS是物理窗口,从行数上控制窗口的尺寸的;

RANGE是逻辑窗口,从列值上控制窗口的尺寸。这个比较难理解,但说白了就简单了,具体解释如下面栗子1.

结合order by子句使用,如果在order by子句后面没有指定窗口子句,则默认为:range between unbounded preceding and current row

------------------------------------------------------------

rt_data表存放了当天每半小时的店铺销售数据

字段stat_date格式yyMMddHHmm

------------------------------------------------------------

1.统计截止到当前时间段的店铺累计销售金额

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select shop_id, stat_date, ordamt, sum(ordamt) over(partition by shop_id order by stat_date)   
  2. from rt_data   
  3. where dt = '2015-01-11' and shop_id = 10026;  
  4.   
  5. 10026   201501120030    5170    5170  
  6. 10026   201501120100    5669    10839  
  7. 10026   201501120130    2396    13235  
  8. 10026   201501120200    1498    14733  
  9. 10026   201501120230    1997    16730  
  10. 10026   201501120300    1188    17918  
  11. 10026   201501120330    598 18516  
  12. 10026   201501120400    479 18995  
  13. 10026   201501120430    1587    20582  
  14. 10026   201501120530    799 21381  

这里order by 后面省去了窗口子句,还原起来就是order by stat_date range between unbounded preceding and current row. 这是什么意思?

就是先按stat_date排序,窗口就是比当前stat_date小的行到当前stat_date的行。

其实,这里写成order by stat_date rows between unbounded preceding and current row是一样的。

2.统计每个时间段的销售占比

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select shop_id, stat_date, ordamt, ordamt / sum(ordamt) over(partition by shop_id)   
  2. from rt_data   
  3. where dt = '2015-01-11' and shop_id = 10026  
  4. order by stat_date;  
  5.   
  6. 10026   201501120900    5406    0.014227  
  7. 10026   201501120930    13098   0.034471  
  8. 10026   201501121000    15679   0.041263  
  9. 10026   201501121030    12134   0.031934  
  10. 10026   201501121100    26259   0.069107  
  11. 10026   201501121130    16516   0.043466  
  12. 10026   201501121200    20127   0.052969  

partition by之后没有使用order by,窗口大小默认就是整个分组。

3.找出2点的销售金额及前半小时的销售金额和后1个小时的销售金额

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select * from (   
  2.     select   
  3.         shop_id,   
  4.         stat_date,  
  5.         ordamt,   
  6.         lag(stat_date,1) over(partition by shop_id order by stat_date),   
  7.         lag(ordamt,1) over(partition by shop_id order by stat_date),   
  8.         lead(stat_date,2) over(partition by shop_id order by stat_date),  
  9.         lead(ordamt,2) over(partition by shop_id order by stat_date)   
  10.     from rt_data   
  11.     where dt = '2015-01-11' and shop_id = 10026   
  12. ) t  
  13. where stat_date = 201501120200;  
  14.   
  15. 10026   201501120200    1498    201501120130    2396    201501120300    1188  

lag(field, N)是取前N行的值,lead(field, N)是取后N行的值。

4.按照销售金额进行排名,金额最大的排最前(limit可以取topn的数)

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select shop_id, stat_date, ordamt, dense_rank() over(partition by shop_id order by ordamt desc)   
  2. from rt_data   
  3. where dt = '2015-01-11' and shop_id = 10026;  
  4.   
  5. 10026   201501121100    26259.0 1  
  6. 10026   201501121200    20127.0 2  
  7. 10026   201501121300    18138.0 3  
  8. 10026   201501121130    16516.0 4  
  9. 10026   201501121400    15956.0 5  
  10. 10026   201501121000    15679.0 6  
  11. 10026   201501122200    14290.0 7  
  12. 10026   201501121430    14203.0 8  
  13. 10026   201501121330    13290.0 9  
  14. 10026   201501120930    13098.0 10  

dense_rank和rank都是排名函数,区别在于dense_rank是连续排名,rank遇到排名并列时,下一列排名跳空。

percent_rank,介于0和1直接的小数形式表示,计算方法是(rank - 1) / (n-1),其中rank为行的序号,n为组的行数,这个暂时不知道有什么地方可以运用,欢迎指导。

5.按销售金额排序,取出前20%的时间段和相应金额

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select * from (  
  2.     select shop_id, stat_date, ordamt, ntile(5) over(partition by shop_id order by ordamt desc) sorted   
  3.     from rt_data   
  4.     where dt = '2015-01-11' and shop_id = 10026   
  5. ) t   
  6. where sorted = 1;  
  7.   
  8. 10026   201501121100    26259.0 1  
  9. 10026   201501121200    20127.0 1  
  10. 10026   201501121300    18138.0 1  
  11. 10026   201501121130    16516.0 1  
  12. 10026   201501121400    15956.0 1  
  13. 10026   201501121000    15679.0 1  
  14. 10026   201501122200    14290.0 1  
  15. 10026   201501121430    14203.0 1  
  16. 10026   201501121330    13290.0 1  
NTILE这个很强大,以前要获取一定比例的数据是非常困难的,NTILE就是把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。

---------------------------------------------------------------------

over语句还可以独立出来,用window重写,但需要注意的是,如下sort by使用了多个字段,如果用range指定窗口的话会出错,需要用rows来指定窗口,因为range是对列的比较,不支持多列比较。

[sql]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. select shop_id, stat_date, ordamt, sum(ordamt) over win as t  
  2. from rt_data   
  3. where dt = '2015-01-11' and shop_id = 10026  
  4. window win as (distribute by shop_id sort by shop_id, ordamt desc rows between unbounded preceding and current row);  

原文地址:http://blog.csdn.net/xiepeifeng/article/details/42676567

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值