龙空技术网

Hive SQL主要开窗函数用法介绍

虾哥学习笔记 177

前言:

此时我们对“mysql开窗函数rank”大概比较看重,咱们都需要分析一些“mysql开窗函数rank”的相关内容。那么小编也在网络上搜集了一些对于“mysql开窗函数rank””的相关文章,希望我们能喜欢,你们快快来学习一下吧!

在开窗函数出现之前,存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成。为了解决这些问题,在2003年ISO SQL标准加入了开窗函数,开窗函数的使用使得这些经典的难题可以被轻松的解决。

下面通过一些简单的需求示例介绍主要的开窗函数。

本例的数据源:

select * from wx_tmp1;

需求1:要在源表中,增加两列,全国总的gmv和各城市的gmv占比。

select *,sum(gmv) over() as all_gmv,

gmv/sum(gmv) over() as gmv_pro

from wx_tmp1;

这就是开窗函数的妙处。SQL标准允许将所有聚合函数用做开窗函数,只需要在聚合函数后加over()即可。

over()可以传入对应的子句来达到不同的效果,下面一一介绍。

需求2:要在源表中,增加两列,各区域的gmv及各分组的gmv。

select *,

sum(gmv) over(partition by area) as area_gmv,

sum(gmv) over(partition by group) as group_gmv

from wx_tmp1;

partition by对表进行分区然后聚合计算每个分区的数据,且同一个select语句中可以同时使用多个开窗函数,而且这些开窗函数并不会相互干扰。

需求3:在源表的基础上,增加一列,按gmv升序排列并计算累计gmv。

select *,

sum(gmv) over(order by gmv rows between unbounded preceding and current row) as leiji_gmv

from wx_tmp1;

order by子句可以对结果集按照指定的排序规则进行排序,并且在一个指定的范围内进行聚合运算。

order by子句的语法为:order by 字段名 range|rows between 边界规则1 and 边界规则2。

range|rows between 边界规则1 and 边界规则2,这个子句又被称为定位框架。

range是按照值的范围进行范围的定义,rows是按照行的范围进行范围的定义,边界范围可取值:

current row:当前行

n preceding:前N行,比如 2 preceding

unbounded preceding:一直到第一条记录

n following:后N行

unbounded following:一直到最后一条记录

这个需求中,计算累计gmv,即计算第一条记录到当条记录的gmv之和。

rows between unbounded preceding and current row,是最常用的定位框架,可以省略。

因此可以简写为以下:

select *,

sum(gmv) over(order by gmv) as leiji_gmv

from wx_tmp1;

需求4:在源表中,增加一列,计算gmv的分组排名。

select *,

count(city) over(partition by group order by gmv desc) as ranks

from wx_tmp1;

分组排名有另外三个开窗函数:

select *,count(city) over(partition by group order by gmv desc) as ranks1,

rank() over(partition by group order by gmv desc) as ranks2,

dense_rank() over(partition by group order by gmv desc) as ranks3,

row_number() over(partition by group order by gmv desc) as ranks4

from wx_tmp1

通过结果可以看出几种排序的差异。ranks2和ranks3的排序在本例中没有体现:

ranks2:如果下面还有一个城市的话,排名是11;ranks3:如果下面还有一个城市的话,排名是10。

需求5:在源表中增加两列,取出每组gmv最大的城市,和最小的城市。

select *,first_value(city) over(partition by group order by gmv desc) as first_city,

first_value(city) over(partition by group order by gmv) last_city

from wx_tmp1

first_value:按分组排序后,取范围内第一个值。相应的还有last_value,按分组排序后,取范围内,最后一个值。

如果这个需求中,按以下写法的话:

select *,first_value(city) over(partition by group order by gmv desc) as first_city,

last_value(city) over(partition by group order by gmv desc) last_city

from wx_tmp1

会发现last_city的结果不是我们想要的。是因为使用了默认定义框架:第一行到当前行的最后一个值。

要纠正这个问题,需要使用定位框架,因为相对麻烦,建议用first_value()替代。

需求6:在源数据中增加两列,第一列取gmv分组排名在当前城市上面1位的城市,第二列取gmv分组排名在当前城市下面1位的城市。

select *,lag(city,1,null) over(partition by group order by gmv desc) as up_city,

lead(city,1,null) over(partition by group order by gmv desc) down_city

from wx_tmp1

如果要取排名前/后两位的城市,调整lag和lead第二个参数即可。第三个参数为默认值,可以省略,省略的话,默认取不到时是NULL,如果不省略的话,取不到时则取指定默认值。

还有一个开窗函数,如下用法:

select *,ntile(2) over(partition by group order by gmv desc) rn from wx_tmp1

即将源表按group分组,并按gmv降序排列后,将每组平均分为2部分。

还有其他聚合函数用法跟sum()一致,就不一一介绍了。

标签: #mysql开窗函数rank