Hive窗口函数

测试数据集

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

题目

查询在2017年4月份购买过的顾客及总人数
1
select name,count(*) over() from test1 where substring(orderdate, 1, 7) = '2017-04' group by name;
查询顾客的购买明细及购买总额
1
select *,sum(cost) over() from test1;
累计计算
求每个人消费金额及购买总额,按照日期进行累加
1
select orderdate,sum(cost) over(order by orderdate) from test1;
求每个人消费金额及购买总额,按人按时间累加
1
select name, orderdate,cost,sum(cost) over(distribute by name) from test1;
查询顾客上次的购买时间
1
select name,orderdate,cost,lag(orderdate, 1) over(partition by name order by orderdate) from test1;

why

  • over()函数

    over() 必须写在聚合函数后面,order() => 开窗
    这个窗口就是一部分数据集, 数据集的作用范围是 前面的聚合函数(只有前面的聚合函数能够使用到窗口里面的数据)
    over() 里面可以传参,如果不传参就是对整个数据集进行开窗(将整个数据集放到一个窗口中)
    over() 聚合函数前,有多少条数据就开几次窗

  • 参数说明
1
2
3
4
5
6
7
8
9
over() 中的参数说明
=> current row : 当前行
=> n preceding : 往前n行
=> n following : 往后n行
=> unbounded : 起点
=> following : 终点
over() 外的参数说明
=> LAG(col, n) : 往前第n行
=> LEAD(col, n) : 往后第n行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
select name,count(*) over() from test1 where substring(orderdate, 1, 7) = '2017-04' group by name;
// 会开两次窗,group by进行了去重
> 结果
mart 2
jack 2

select name,count(*) over() from test1 where substring(orderdate, 1, 7) = '2017-04';
// 有几个name 就会开几个窗(5个)
> 结果
mart 5
mart 5
mart 5
mart 5
jack 5

select orderdate,sum(cost) over(order by orderdate) from test1;
// over() 中限制了窗口的大小,此时窗口的大小是根据 orderdate来判断,又因为 orderdate 进行了order by ,所以第一次开窗是最小的orderdate,逐步变大,sum() 中拿到的值也逐渐变多(窗口逐渐变大),直到最后一个orderdate,窗口数据集就是整个数据集。

select name, orderdate,cost,sum(cost) over(distribute by name) from test1;
// distribute => 作用和group by 类似,可以起到分组去重的作用,over() 中不能使用 group by

select name, orderdate,cost,sum(cost) over(distribute by name sort by orderdate) from test1;
select name, orderdate,cost,sum(cost) over(prtition by name order by orderdate) from test1;
// sort byorder by 排序 order by 针对的是整体,sort by针对的是分组(分区)内的数据 distribute by 和 sort by 一般是连用, partition by 和 oreder by 连用

select name,orderdate,cost,lag(orderdate, 1) over(partition by name order by orderdate) from test1;
// lag(col, n) 是找到col类的前面第几行,针对上面的sql语句,每次找到的都是当前行的前面一行 lag() 会受到分区的阻挡,如果同时用到LAG() 和 LEAD() 需要在每个后面都跟上 over() ,因为over 只对它前面的一个聚合函数提供内容