从本文开始介绍Hive中开窗函数系列。这类函数叫法很多,包括分析函数、窗口函数、开窗函数、分析窗口函数,其实说的都是一类函数,本系列博客后续均采用开窗函数的命名方式。
这里直接上百度百科的定义:
开窗函数用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。
开窗函数的语法为:
over(partition by 列名1,列名2 …… order by 列名3,列名4 …… [desc])
括号中的两个关键词partition by 和order by 可以只出现一个。
partition by 和order by 后面的列名可以根据需求设定任意数量个列名。
order by后面可以选择是否跟desc,加上为倒序排序(从大到小),不加则默认为从小到大排序。
over() 前面是一个函数。
在Hive中开窗函数按功能主要分为以下四类:
本文主要介绍第一类开窗函数,即用于组内累计统计的开窗函数:sum、avg、min、max。
数据准备:
新建test.txt文件,输入如下的三列数据,以空格分隔。第一列是月份,第二列代表商铺名称,第三列代表该商铺该月营业额(万元)。
[root@hadoop ~]# vim test.txt
2019-01 a 10
2019-02 a 20
2019-03 a 30
2019-01 b 10
2019-02 b 20
2019-03 b 30
在hive中新建表temp_test9,将test文件中的数据插入,查看数据。
CREATE TABLE temp_test9 (
month STRING comment '月份'
,shop STRING comment '商铺名称'
,money STRING comment '营业额(万元)'
) row format delimited fields terminated BY ' ';
load data local inpath '/root/test.txt' into table temp_test9;
select * from temp_test9;
temp_test9.month temp_test9.shop temp_test9.money
2019-01 a 10
2019-02 a 20
2019-03 a 30
2019-01 b 10
2019-02 b 20
2019-03 b 30
求商店a每个月从1月累计到该月的总营业额,即:
SELECT month
,SUM(MONEY) OVER (
ORDER BY month --按照月份进行排序,然后默认从起点行到当前行做累计求和
) AS money_leiji
FROM temp_test9
WHERE shop = 'a'; --开窗函数不用写group by
结果:
month money_leiji
2019-01 10.0
2019-02 30.0
2019-03 60.0
同时求出商店a、b每个月从1月累计到该月的总营业额
SELECT shop
,month
,SUM(MONEY) OVER (
PARTITION BY shop ORDER BY month --先按照shop进行分组,然后每个组内再按照月份进行排序,最后默认从起点行到当前行做累计求和
) AS money_leiji
FROM temp_test9;
结果:
shop month money_leiji
a 2019-01 10.0
a 2019-02 30.0
a 2019-03 60.0
b 2019-01 10.0
b 2019-02 30.0
b 2019-03 60.0
只分组求和也不会报错,但这样没什么意义,不如直接使用group by。
SELECT shop
,month
,SUM(MONEY) OVER (PARTITION BY shop) AS money_leiji
FROM temp_test9;
shop month money_leiji
a 2019-03 60.0
a 2019-02 60.0
a 2019-01 60.0
b 2019-03 60.0
b 2019-02 60.0
b 2019-01 60.0
不写month也会统计出来3个组内求和
SELECT shop
,SUM(money) OVER (
PARTITION BY shop
) AS money_leiji
FROM temp_test9;
shop money_leiji
a 60.0
a 60.0
a 60.0
b 60.0
b 60.0
b 60.0
除了上面常用的累计求和方式之外,Hive还允许自定义累计方式。默认的累计方式是按起点行到当前行做累计,自定义累计方式主要有以下4种:
这几种自定义的累计方式应用场景很少,可以不掌握,这里只介绍一下语法:
1 PRECEDING指往前1行,这里可以根据需求任意指定数值
OVER (PARTITION BY 列名1 ORDER BY 列名2 ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
1 FOLLOWING指往后1行,这个值可以根据需求指定任意数值
OVER (PARTITION BY 列名1 ORDER BY 列名2 ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)
1 PRECEDING指往前1行,1 FOLLOWING指往后1行,这两个值均可以根据需求指定任意数值
OVER (PARTITION BY 列名1 ORDER BY 列名2 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
OVER (PARTITION BY 列名1 ORDER BY 列名2 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
其他的开窗函数和求和的累计逻辑都是相同的。
举例:
同时求出商店a、b每个月从1月累计到该月的平均营业额
SELECT shop
,month
,AVG(MONEY) OVER (
PARTITION BY shop ORDER BY month --先按照shop进行分组,然后每个组内再按照月份进行排序,最后默认从起点行到当前行做累计求均值
) AS money_leiji
FROM temp_test9;
结果:
shop month money_leiji
a 2019-01 10.0
a 2019-02 15.0
a 2019-03 20.0
b 2019-01 10.0
b 2019-02 15.0
b 2019-03 20.0
举例:
同时求出商店a、b每个月从1月累计到该月的营业额最大值
SELECT shop
,month
,MAX(MONEY) OVER (
PARTITION BY shop ORDER BY month --先按照shop进行分组,然后每个组内再按照月份进行排序,最后默认从起点行到当前行做累计求最大值
) AS money_leiji_max
FROM temp_test9;
结果:
shop month money_leiji_max
a 2019-01 10
a 2019-02 20
a 2019-03 30
b 2019-01 10
b 2019-02 20
b 2019-03 30
举例:
同时求出商店a、b每个月从1月累计到该月的营业额最小值
SELECT shop
,month
,MIN(MONEY) OVER (
PARTITION BY shop ORDER BY month --先按照shop进行分组,然后每个组内再按照月份进行排序,最后默认从起点行到当前行做累计求最小值
) AS money_leiji_min
FROM temp_test9;
结果:
shop month money_leiji_min
a 2019-01 10
a 2019-02 10
a 2019-03 10
b 2019-01 10
b 2019-02 10
b 2019-03 10
能看到这里的同学,就右上角点个赞吧,3Q~