Hive(三)--窗口函数

窗口函数

窗口函数也称为OLAP(Online Analytical Processing)函数,是对一组值进行操作,不需要使用Group by子句对数据进行分组,还能在同一行返回原来行的列和使用聚合函数得到的聚合列。
窗口函数是用于分析用的一类函数,要理解窗口函数要先从聚合函数说起。聚合函数是将某列中多行的值合并为一行,比如sum、count等。 而窗口函数则可以在本行内做运算,得到多行的结果,即每一行对应一行的值。 通用的窗口函数可以用下面的语法来概括:
<窗口函数>() over ( [partition by <列>] [order by <排序列>] [ASC/DESC] (rows | range) <范围条件> )
窗口函数按照功能大致分为四类: 计算、取值、排序、序列
在这里插入图片描述

数据准备
saml,2018-01-01,10
tony,2018-01-02,15
saml,2018-02-03,23
tony,2018-01-04,29
saml,2018-01-05,46
saml,2018-04-06,42
tony,2018-01-07,50
saml,2018-01-08,55
mart,2018-04-08,62
mart,2018-04-09,68
neil,2018-05-10,12
mart,2018-04-11,75
neil,2018-06-12,80
mart,2018-04-13,94
-- 创建表t_order
create table if not exists t_order(
 name  string,-- 姓名
 orderedate string,-- 购买日期
 cost  int -- 购买数量
)
row format delimited fields terminated by ',';

-- 加载数据
--  1、本地加载
load data local inpath '/testHive/day04/order.csv' overwrite into  table t_order;
--  2、HDFS加载
load data inpath '/user/hive/order.csv' overwrite into table t_order;
 
窗口函数语法
  • over开窗
    当我们查询一个表中所有时可以用 * 号,查询总量是可以count(),但如果既要查询所有数据又要查询总量直接使用,count(*)显然是不对的,这是就需要用到窗口函数
-- 查询所有明细
select * from  t_order;
-- 查询总量
select  count(*) from  t_order;
-- 同时查出明细和总量
-- 错误的(未使用窗口函数)
select  *,count(*) from  t_order;
-- 使用窗口函数
select  *,count(*) over() from  t_order;

在这里插入图片描述

注意:窗口函数是针对每一行数据的,如果over中没有参数,默认的全部结果集
例题:

-- 需求:查询在2018年1月份购买的顾客购买明细及总人数
-- 方法一
select  *,count(*) over ()
from  t_order
where  substr(orderedate,1,7)='2018-01';
-- 方法二
select  *,count(*) over ()
from  t_order 
where  month(orderedate)=1 and year(orderedate)=2018;

在这里插入图片描述

  • partition by子句
    在over窗口中进行分区可以使用partition by 子句,对某一列进行分区统计,窗口的大小就是分区的大小
-- 需求:查看顾客的购买明细及月购买总额
select *,sum(cost) over (partition by  year(orderedate),month(orderedate))
from t_order;

在这里插入图片描述

  • order by
    order by子句会对输入的数据强制排序
select *,sum(cost) over (partition by month(orderedate) order by orderedate) from t_order;

在这里插入图片描述

  • window 子句
    window子句可以对窗口的结果做更细粒度的划分
    n preceding:往前n条
    n following:往后n条
    current row:当前行
    unbounded:起点
    unbounded preceding:从前面的起点开始
    unbounded following:表示到后面的终点结束
select *,
sum(cost) over() as co1,-- 所有行相加
sum(cost) over(partition by name) as co2,-- 按name分组,组内数据相加
sum(cost) over(partition by name order by  orderedate) as co3,-- 按name分组,组内数据累加
sum(cost) over(partition by name order by  orderedate rows between UNBOUNDED PRECEDING AND current row ) as co4,-- 和col3一样,由起点 到当前行的聚合
sum(cost) over(partition by name order by  orderedate rows between 1 PRECEDING AND current row ) as co5,-- 当前行和前面一行做聚合
sum(cost) over(partition by name order by  orderedate rows between 1 PRECEDING and 1 following ) as co6,-- 但行和前边一行及后面一行
sum(cost) over(partition by name order by  orderedate rows between current row and unbounded following) as co7-- 当前行及及后面所有行
from t_order;

在这里插入图片描述

取值
  • first_value和last_value
    first_value取分区内排序后,截止到当前行,第一个值
    last_value分组内排序后,截止到当前行,最后一个值
select *,
-- 获取第一次购买的时间
 first_value(orderedate) over (partition by name order by orderedate) as  first,
-- 获取最后一次购买的时间
 last_value(orderedate) over (partition by name order by orderedate) as  last
from t_order;

在这里插入图片描述

  • lag和lead函数
    lag返回当前数据行的上一行数据
    lead返回当前数据行的下一行数据
-- 查询顾客上次购买的时间
select *,
 lag(orderedate) over  (partition by name order by orderedate) as time
from t_order;

结果如图:null是因为按日期排序,当前记录没有上一条记录
上述查询结果

-- 需求:查询顾客下次购买的时间
select *,
lead(orderedate) over  (partition by name order by orderedate) as time
from t_order;

结果如图:null是因为按日期排序,当前记录没有下一条记录
上述查询结果

排序
  • rank
    排序,排序值相同,名次相同,会在排序中留空
-- 按照价格进行排序,名次相同留空
select *,rank() over(order by cost desc) from t_order;

在这里插入图片描述

  • dense_rank
    排序,排序值相同,名次相同,会在排序中留空
-- 按照价格进行排序,名次相同不留空
select *,dense_rank() over(order by cost desc) from t_order;

在这里插入图片描述

  • row_number
-- 按名字分组,组内按日期排序给出序号
select *,row_number() over(partition by name order by orderedate) 
from t_order;

在这里插入图片描述

  • ntile
    用于对分组数据按照顺序切片分成n片,返回当前切片值
    如果切片不均匀,默认增加第一个切片的分布,如下图saml有5条记录,ntile切片数为4,切片不均,多出来的一条默认增加到第一个切片,故saml有两个切片值为1
select *,ntile(4) over  (partition by name) as sliceValue
from t_order order by name,sliceValue;

在这里插入图片描述
例题:打印出截止目前每个人一半(50%)的购买细节

select *
from
(select *,ntile(2) over (partition by name) as sliceValue  from t_order) as t_order1
where sliceValue=1;

在这里插入图片描述

序列
  • cume_dist
    该函数的值为:小于等于当前值的行数/分组内总行数
-- 按名字分组,统计小于等于当前消费金额的次数所占总次数的比例
select name,cost,cume_dist() over(partition by name order by cost) from t_order;

在这里插入图片描述

  • percent_rank
    当前行的RANK值-1/分组内总行数-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值