5.窗口函数

 数据准备:

-- 数据准备
create table business(
    name string,        -- 顾客
    orderdate string,  -- 下单日期
    cost int             -- 购买金额
) 
row format delimited fields terminated by ',';
load data local inpath "/opt/module/hive/datas/business.txt" 
into table business;

   

查询2017年4月购买过的顾客:

select distinct name from business 
where substring(orderdate, 1,7) = '2017-04'; //取1到7位下标

  如果想求2017年4月购买过的人数:

select count(distinct name)
from business
where substring(orderdate,1,7) = "2017-04";

1.over():给聚合函数开窗口

ps.在明细查询中进行汇总,必须使用窗口函数!

如果希望将购买过的人和购买过的人次放在一张表里面展示:

select distinct name,count(distinct name) over() // 什么都不写就代表全表
from business
where substring(orderdate, 1, 7)='2017-04';

ps.count()要么跟group by结合,要么跟开窗函数结合 

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

也就是按月求下汇总

select name,
       orderdate,
       cost,
       sum(cost) over(partition by substring(orderdate, 1, 7)) month_total
from business;

查询每个顾客的截止到当日的累计消费:

select name,
       orderdate,
       cost,
       sum(cost) over(partition by name order by orderdate 
                      rows between unbounded preceding and current row),--累加
       sum(cost) over(partition by name order by orderdate 
                      rows between 1 preceding and current row) --最近两次购买
from business;

解释:首先

select * from business order by name, orderdate;

获得

                         

然后在这个表的基础上新添一行,求累计消费

因为是求每个顾客,所以是partition by name;

求累计消费,所以是order by orderdate;

order by 经常rows between and 连用

ps.这里的开窗函数表示给每行单独开窗口

CURRENT ROW

当前行
n PRECEDING往前n行数据
n FOLLOWING往后n行数据
UNBOUNDED起点
UNBOUNDED PRECEDING表示从前面的起点(unbounded 表示无界)
UNBOUNDED FOLLOWING表示到后面的终点

求购买明细和截至当日来过店的顾客

select name, orderdate, cost,
       collect_set(name) over(order by orderdate 
                             rows between UNBOUNDED preceding and current row)
from business;

2.其他结合有序窗口使用函数

2.1 lag && lead

使用方法:lag() over() as 别名
-- lag(col, n, default_value) over(有序窗口)
-- 显示col这一列n行之前的数据,如果没有,展示default_value
-- lead(col, n, default_value) over(有序窗口)
-- 显示col这一列n行之后的数据,如果没有,展示default_value

 查询购买明细和每个人上一次的到店时间

select name, orderdate, cost,
       lag(orderdate, 1, '1970-01-01') 
           over(partition by name order by orderdate) as last_order,
       lead(orderdate, 1, '2050-01-01') 
           over(partition by name order by orderdate) as next_order
from business;

2.2  ntile

使用方式:

-- 将数据分为n组,返回当前行的组号
-- ntile(n) over(有序窗口)

例如:

订单明细按照订单时间分为5组:

select name,orderdate,cost,
       ntile(5) over(order by orderdate) zu
from business;

查看前20%

-- 在上表的基础上
select name, orderdate, cost
from t1 where zu=1;

2.3 rank&&dense_rank&&row_number

使用方法:

-- 排序
rank() over (有序窗口)
dense_rank() over (有序窗口)
row_number() over (有序窗口)

数据准备:

求各科成绩排名

select name,subject,score,
       rank() over(partition by subject order by score desc) `rank`,
       dense_rank() over(partition by subject order by score desc) `d_r`,
       row_number() over(partition by subject order by score desc) `r_n`
from score;

可以看出三种排序的不同:

 在上表基础上,查询各科的前三名

select name,subject,score
from t1
where `rank`<=3;

2.4 first_value && last_value 

-- 使用方法
frist_value(col,boolean) over(有序窗口) //返回这一列的第一行,如果为true,则忽略null
last_value(col,boolean) over(有序窗口)

 以下表为例:

                      

 查询表明细,以及截至日期当日,每人的第一笔和最后一笔大于50元的消费日期

查询结果:

                                 

总结:在以下两种场景下需要使用开窗:

1.在明细查询中展示汇总结果

2.结合其他函数使用(如lag,lead,rank等) 

3.练习题

数据准备:

     

 求每个品类消费排名的前10:

同样是使用子查询:

// 在原来的表格上新加一行命名为rnk
select id, category_id,sales_sum
          rank() over(partition by category_id order by sales_sum desc ) rnk
from sales 
select category_id
from  (
select id, category_id,sales_sum
       rank() over(partition by category_id order by sales_sum desc ) rnk
from sales 
) t1
where rnk<=10

 求各品类  销量前10的商品列表  以及前10商品的销售总额

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值