hive 开窗函数理解区别range和row以及默认省略语句

数据准备:name,orderdate,cost


jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-01,29
jack,2017-01-01,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

需求

  1. 查询在2017年4月份购买过的顾客及总人数
  2. 查询顾客的购买明细及月购买总额
  3. 上述的场景,要将cost按照日期进行累加
  4. 查询顾客上次的购买时间
  5. 查询前20%时间的订单信息

创建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;

按需求查询数据

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

select name,count(*) over ()

from business

where substring(orderdate,1,7) = '2017-04'

group by name;

查询每个月购买总额及顾客的购买明细

select name,orderdate,cost,sum(cost) over(partition by month(orderdate)) from business;

上述的场景,要将cost按照日期进行累加

 

select name,orderdate,cost,
sum(cost) over() as s1,
sum(cost) over(partition by name) as s2,
sum(cost) over(partition by name order by orderdate ) as s3,
sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as s4
from business;

+-------+-------------+-------+------+------+------+------+
| name  |  orderdate  | cost  |  s1  |  s2  |  s3  |  s4  |
+-------+-------------+-------+------+------+------+------+
| jack  | 2017-01-01  | 10    | 661  | 176  | 56   | 10   |
| jack  | 2017-01-01  | 46    | 661  | 176  | 56   | 56   |
| jack  | 2017-01-08  | 55    | 661  | 176  | 111  | 111  |
| jack  | 2017-02-03  | 23    | 661  | 176  | 134  | 134  |
| jack  | 2017-04-06  | 42    | 661  | 176  | 176  | 176  |
| mart  | 2017-04-08  | 62    | 661  | 299  | 62   | 62   |
| mart  | 2017-04-09  | 68    | 661  | 299  | 130  | 130  |
| mart  | 2017-04-11  | 75    | 661  | 299  | 205  | 205  |
| mart  | 2017-04-13  | 94    | 661  | 299  | 299  | 299  |
| neil  | 2017-05-10  | 12    | 661  | 92   | 12   | 12   |
| neil  | 2017-06-12  | 80    | 661  | 92   | 92   | 92   |
| tony  | 2017-01-01  | 29    | 661  | 94   | 29   | 29   |
| tony  | 2017-01-02  | 15    | 661  | 94   | 44   | 44   |
| tony  | 2017-01-07  | 50    | 661  | 94   | 94   | 94   |
+-------+-------------+-------+------+------+------+------+
 

select name,orderdate,cost,
sum(cost) over(range between unbounded preceding and current row) as s1,
sum(cost) over(partition by name range between unbounded preceding and current row) as s2,
sum(cost) over(partition by name order by orderdate range between unbounded preceding and current row) as s3,
sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as s4,

sum(cost) over(partition by name  rows between UNBOUNDED PRECEDING and current row ) as s5
from business;

+-------+-------------+-------+------+------+------+------+
| name  |  orderdate  | cost  |  s1  |  s2  |  s3  |  s4  |
+-------+-------------+-------+------+------+------+------+
| jack  | 2017-01-01  | 10    | 661  | 176  | 56   | 10   |
| jack  | 2017-01-01  | 46    | 661  | 176  | 56   | 56   |
| jack  | 2017-01-08  | 55    | 661  | 176  | 111  | 111  |
| jack  | 2017-02-03  | 23    | 661  | 176  | 134  | 134  |
| jack  | 2017-04-06  | 42    | 661  | 176  | 176  | 176  |
| mart  | 2017-04-08  | 62    | 661  | 299  | 62   | 62   |
| mart  | 2017-04-09  | 68    | 661  | 299  | 130  | 130  |
| mart  | 2017-04-11  | 75    | 661  | 299  | 205  | 205  |
| mart  | 2017-04-13  | 94    | 661  | 299  | 299  | 299  |
| neil  | 2017-05-10  | 12    | 661  | 92   | 12   | 12   |
| neil  | 2017-06-12  | 80    | 661  | 92   | 92   | 92   |
| tony  | 2017-01-01  | 29    | 661  | 94   | 29   | 29   |
| tony  | 2017-01-02  | 15    | 661  | 94   | 44   | 44   |
| tony  | 2017-01-07  | 50    | 661  | 94   | 94   | 94   |
+-------+-------------+-------+------+------+------+------+
 

两者运行结果一致, 说明省略的 即range between unbounded preceding and current row

官方给出了说省略 的是row between unbounded preceding and unbounded following

如果有order by 则是省略的range between unbounded preceding and unbounded following

个人解释:

s1  range没有partition 所以current row 没有界限 和unbounded following 一致 结果(此处不再显示演示结果) 

s2  unbounded preceding 即 同一个partition中的首行 不受order by 影响, current row 即当前行 ,当前行即name=jack , 因为此处为range开窗范围

range 代表name=jack的所有行, 所以结果为5个jack行之和, 关于range和row的区别请参照 https://blog.csdn.net/xinqiku/article/details/96362796

s3 unbounded preceding 即 同一个partition中的首行 不受order by 影响, current row 受order by orderdate影响 , 当前行即 name=jack, orderdate =2017-01-01 联合, 又因为是range开窗 所以结果为2行name=jack, orderdate =2017-01-01之和 (如果current row 改成unbounded following , unbounded following 则不受order by 影响 而直接指向partition的末行 结果为jack五行之和 ,此处不再显示演示结果)

s4 unbounded preceding 即 同一个partition中的首行 , current row 因为是row 开窗范围, 即当前行name=jack这一行的和, 如果当前行移到下一行,即为当前行之前的所有行之和

此为刚接触hive 总结规律所写, 不当之处请大佬留言赐教!

 

查询顾客上次的购买时间

select 
name, orderdate, cost,
lag(orderdate, 1 ,'1970-01-01') over(partition by name order by orderdate)
from
business

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

SELECT *
FROM (
    SELECT *
        ,ntile(5) OVER (
            ORDER BY orderdate
            ) n
    FROM orders
    ) t
WHERE t.n = 1;

解释:

SELECT *
        ,ntile(5) OVER (
            ORDER BY orderdate
            ) n
    FROM orders

+----------------+---------------------+----------------+----+
| business.name  | business.orderdate  | business.cost  | n  |
+----------------+---------------------+----------------+----+
| jack           | 2017-01-01          | 10             | 1  |
| tony           | 2017-01-01          | 29             | 1  |
| jack           | 2017-01-01          | 46             | 1  |
| tony           | 2017-01-02          | 15             | 2  |
| tony           | 2017-01-07          | 50             | 2  |
| jack           | 2017-01-08          | 55             | 2  |
| jack           | 2017-02-03          | 23             | 3  |
| jack           | 2017-04-06          | 42             | 3  |
| mart           | 2017-04-08          | 62             | 3  |
| mart           | 2017-04-09          | 68             | 4  |
| mart           | 2017-04-11          | 75             | 4  |
| mart           | 2017-04-13          | 94             | 4  |
| neil           | 2017-05-10          | 12             | 5  |
| neil           | 2017-06-12          | 80             | 5  |
+----------------+---------------------+----------------+----+

输出为后续加了 n字段数字分为5桶 每桶为一样数字, 让后再查询此表 得出前20%数据

ntile 参考 https://blog.csdn.net/BabyFish13/article/details/78550601

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hive开窗函数主要分为排序开窗和聚合开窗两类。在排序开窗函数中,常用的函数有row_number()、rank()、dense_rank()和percent_rank()。其中,row_number()用于给每一行分配一个唯一的行号,rank()用于对组内的行进行排名,dense_rank()也是对组内的行进行排名,但排名是连续的,而percent_rank()用于计算给定行的百分比排名,可以用来计算超过了百分之多少的人。\[3\] 在使用Hive开窗函数时,可以通过rows/range between来控制窗口函数的范围。这个功能在满足业务需求时非常有用。通过使用rows/range between,可以根据自己的需求任意地控制窗口函数的范围。\[1\] 需要注意的是,在Hive中,开窗函数的使用是在2003年ISO SQL标准中引入的,它解决了许多用SQL语句难以解决的问题。在开窗函数出现之前,很多问题都需要通过复杂的相关子查询或存储过程来解决。而开窗函数的使用使得这些经典的难题可以轻松地解决。\[2\] #### 引用[.reference_title] - *1* *3* [大数据-Hive开窗函数](https://blog.csdn.net/MsSpark/article/details/122051503)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Hive SQL主要开窗函数用法介绍](https://blog.csdn.net/weixin_43025027/article/details/124388152)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值