Hive学习笔记:05Hive中常用分析函数使用解析


本文将介绍Hive SQL中常用的窗口分析函数的使用,这些函数的用法不仅仅适用于Hive,对于很多数数据库来说同样也适用,比如SParkSQL,FlinkSQL以及Mysql8,Oracle,MSSQL等传统的关系型数据库。

测试环境准备

如有一张表stock_hq,表格中的数据如下所示:

TDATESECCODEBLOCKAMOUNTPRICE
20221113000001.szA0121010.10
20221113000002.szA022109.10
20221113000003.szA012108.10
20221114000001.szA0121010.10
20221114000002.szA022109.10
20221114000003.szA012108.10
20221116000001.szA0121010.10
20221116000002.szA022109.10
20221116000003.szA012108.10
20221117000001.szA0111010.10
20221117000002.szA021109.10
20221117000003.szA011109.10
20221118000001.szA0110010.10
20221118000002.szA0210010.10
20221118000003.szA0110010.10

常用的窗口分析函数

RANK()

  • 功能:

排名,如果值相同,则排名并列,下一个排名会出现跳跃,即排名是不连续的。比如有前4个值一样,那么前4行并列第一,第5行的排名则为5.

  • 示例:
    按照证券代码分组,统计出价格由低到高的排名。
select seccode,TDATE,AMOUNT,PRICE,RANK() OVER(PARTITION BY SECCODE ORDER BY PRICE) AS RANK_BY_PRICE
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICERANK_BY_PRICE
000001.sz2022111810010.101
000001.sz2022111711010.101
000001.sz2022111321010.101
000001.sz2022111421010.101
000001.sz2022111621010.101
000002.sz202211171109.101
000002.sz202211132109.101
000002.sz202211142109.101
000002.sz202211162109.101
000002.sz2022111810010.105
000003.sz202211132108.101
000003.sz202211142108.101
000003.sz202211162108.101
000003.sz202211171109.104
000003.sz2022111810010.105

由上面的输出结果,我们可以很明显的看出RANK_BY_PRICE的排名是不连续的。

ROW_NUMBER()

  • 功能:

按照排序的顺序输出窗口中的数据的行号信息,不会出现排名相同的情况,且排名是连续的。即使是值相同,排名也会按照其排序顺序递增。

  • 示例:
    按照证券代码分组,统计出价格由低到高的排名。
select seccode,TDATE,AMOUNT,PRICE,ROW_NUMBER () OVER(PARTITION BY SECCODE ORDER BY PRICE) AS RANK_BY_PRICE
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICERANK_BY_PRICE
000001.sz2022111621010.101
000001.sz2022111810010.102
000001.sz2022111711010.103
000001.sz2022111421010.104
000001.sz2022111321010.105
000002.sz202211162109.101
000002.sz202211171109.102
000002.sz202211142109.103
000002.sz202211132109.104
000002.sz2022111810010.105
000003.sz202211162108.101
000003.sz202211142108.102
000003.sz202211132108.103
000003.sz202211171109.104
000003.sz2022111810010.105

由上面的输出结果,我们可以很明显的看出RANK_BY_PRICE的值是连续递增的,即使Price的值一样。

DENSE_RANK()

  • 功能:

按照排序的顺序输出窗口中的数据的排名,值相同时,排名并列,下一个排名是连续递增的,不会出现跳跃情况。即如果前4行的值相同,则前4行并列第1,第5行的排名则为第2。

  • 示例:
    按照证券代码分组,统计出价格由低到高的排名。
select seccode,TDATE,AMOUNT,PRICE,DENSE_RANK() OVER(PARTITION BY SECCODE ORDER BY PRICE) AS RANK_BY_PRICE
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICERANK_BY_PRICE
000001.sz2022111711010.101
000001.sz2022111810010.101
000001.sz2022111421010.101
000001.sz2022111621010.101
000001.sz2022111321010.101
000002.sz202211171109.101
000002.sz202211142109.101
000002.sz202211162109.101
000002.sz202211132109.101
000002.sz2022111810010.102
000003.sz202211142108.101
000003.sz202211162108.101
000003.sz202211132108.101
000003.sz202211171109.102
000003.sz2022111810010.103

由上面的输出结果,我们可以很明显的看出RANK_BY_PRICE的值在Price的值相同时是重复的,且是连续递增的。

PERCENT_RANK()

  • 功能:

与 PERCENT 函数类似,PERCENT_RANK 函数为窗口的 ORDER BY 子句所指定列中的值返回秩,以介于 0 和 1 之间的小数形式表示.

  • 计算方法: (RANK - 1)/(N- 1)。

    • RANK: RANK为上述RANK()函数的排名
    • N:为当前窗口的总函数
  • 示例:
    按照证券代码分组,统计出价格由低到高的PERCENT_RANK。

select seccode,TDATE,AMOUNT,PRICE,RANK() OVER(PARTITION BY SECCODE ORDER BY PRICE) AS RANK_BY_PRICE,
PERCENT_RANK () OVER(PARTITION BY SECCODE ORDER BY PRICE) AS PERCENT_RANK_BY_PRICE
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICERANK_BY_PRICEPERCENT_RANK_BY_PRICE
000001.sz2022111810010.1010.0
000001.sz2022111421010.1010.0
000001.sz2022111621010.1010.0
000001.sz2022111711010.1010.0
000001.sz2022111321010.1010.0
000002.sz202211142109.1010.0
000002.sz202211162109.1010.0
000002.sz202211171109.1010.0
000002.sz202211132109.1010.0
000002.sz2022111810010.1051.0
000003.sz202211142108.1010.0
000003.sz202211162108.1010.0
000003.sz202211132108.1010.0
000003.sz202211171109.1040.75
000003.sz2022111810010.1051.0

由上面的输出结果,我们可以很明显的看出PERCENT_RANK_BY_PRICE的值等于RANK_BY_PRICE的值-1 再除以每个分区窗口的总行数。

CUME_DIST()

  • 功能:

如果是按照升序排列:统计出小于等于当前排序值的行数所占当前分区窗口总行数的比例。

如果是按照排序字段的降序:则统计出大于等于当前排序字段的值的行数所占当前分区窗口总行数的比例。

  • 示例:
    按照证券代码分组,统计出成交额由低到高的CUME_DIST。
select seccode,TDATE,AMOUNT,PRICE,CUME_DIST () OVER(PARTITION BY SECCODE ORDER BY AMOUNT) AS CUME_DIST_BY_AMOUNT
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICECUME_DIST_BY_AMOUNT
000001.sz2022111810010.100.2
000001.sz2022111711010.100.4
000001.sz2022111321010.101.0
000001.sz2022111421010.101.0
000001.sz2022111621010.101.0
000002.sz2022111810010.100.2
000002.sz202211171109.100.4
000002.sz202211132109.101.0
000002.sz202211142109.101.0
000002.sz202211162109.101.0
000003.sz2022111810010.100.2
000003.sz202211171109.100.4
000003.sz202211132108.101.0
000003.sz202211142108.101.0
000003.sz202211162108.101.0

结果解析:如000001.sz的分区窗口,总行数是5,第一条数据AMOUNT的值是100,小于等于100的行数只有1条(它自己),则CUME_DIST的值未1/5=0.2;
第二条数据AMOUNT的值是110,小于等于110的行数的有2条,则为2/5=0.4;
后续的数据的计算同理,在此就不在赘述。

NTILE(N)

  • 功能:

用于将分组数据按照顺序切分成N片,返回当前切片值。将一个有序的数据集划分为多个桶(bucket),并为每行分配一个适当的桶数(切片值,第几个切片,第几个分区等概念)。它可用于将数据划分为相等的小切片,为每一行分配该小切片的数字序号。

N的值默认为1.

分片特点:尽可能的均匀分布到分片中,如果分片不均匀,则默认增加到前面的分片中。比如5条数据分成2片,则第一个分片3条,第2个分片2条。如果分成3个分片,则第一个分片2条,第2个分片2条,第3个分片1条。

TIPS:: NTILE不支持ROWS BETWEEN,RANGE BETWEEN,

  • 示例:
    按照证券代码分组,按照AMOUNT排序,将每个窗口的数据划分成3个分片,返回每行的分片信息。
select seccode,TDATE,AMOUNT,PRICE,NTILE(3) OVER(PARTITION BY SECCODE ORDER BY AMOUNT) AS NTILE_BY_AMOUNT
from stock_hq sh ;

输出:

seccodeTDATEAMOUNTPRICENTILE_BY_AMOUNT
000001.sz2022111810010.101
000001.sz2022111711010.101
000001.sz2022111421010.102
000001.sz2022111321010.102
000001.sz2022111621010.103
000002.sz2022111810010.101
000002.sz202211171109.101
000002.sz202211142109.102
000002.sz202211132109.102
000002.sz202211162109.103
000003.sz2022111810010.101
000003.sz202211171109.101
000003.sz202211142108.102
000003.sz202211132108.102
000003.sz202211162108.103
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值