hive窗口分析函数使用详解系列二之分组排序窗口函数

1.综述

我们讨论面试中各大厂的SQL算法面试题,往往核心考点就在于窗口函数,所以掌握好了窗口函数,面对SQL算法面试往往事半功倍。

已更新第一类聚合函数类,点击这里阅读 hive窗口函数聚合函数类

本节介绍Hive聚合函数中的第二类聚合函数:分组排序窗口函数。

这些函数的用法不仅仅适用于Hive,对于很多数数据库来说同样也适用,比如SparkSQL,FlinkSQL以及Mysql8,Oracle,MSSQL等传统的关系型数据库。

如果论使用的广泛性,hive窗口函数中我们使用最广泛的就是排序类窗口函数,我们通常一提起窗口函数,想到的就是这类排序类窗口函数,它在我们进行数据去重中扮演了至关重要的角色。

1.1 Hive窗口函数分类

Hive提供的窗口函数可以分为一下几类

  • 聚合函数类
count() over();
sum() over();
max() over();
min() over();
avg() over();
  • 分组排序类
row_number() over();
rank() over();
dense_rank() over();
percent_rank() over();
cume_dist() over();
ntile() over();
  • 求偏移量类
lead() over();
lag() over();
first_value() over();

1.2 分析函数语法

分析函数 over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置)

具体解析

over()括号内为空时,是直接进行计算。

其中partition by 列名 是按指定列进行分组,进而进行计算。

最后的order by 列名 是按照指定列进行排序,进而进行计算。

1.3 基础数据准备

create table if not exists temp.user_info (`id` bigint comment '用户id',`client` string comment '客户端',`gender` int comment '性别,0女1男',`constellation` string comment '星座',`age` int comment '年龄',`pv` bigint comment '访问量',`chat_num` bigint comment '聊天次数'
) comment '用户信息测试临时表' 

数据预览

idclientgenderconstellationagepvchat_num
1ios0处女座291743
2ios1双鱼座262632
3android1双鱼座3523239
4ios1水瓶座32573
5ios1射手座33676
6ios1双子座36815
7ios1狮子座29684
8ios1狮子座28193
9ios0射手座324792
10ios1白羊座2625536

2.各分组排序类函数的使用

2.1 row_number

  • 功能

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

  • 示例

按照星座分组,统计出pv由高到低的排名。

select id,client,gender,row_number() over(partition by constellation order by pv desc) as rank_id
from temp.user_info where id <= 10

数据结果:

idclientgenderconstellationpvrank_id
6ios1双子座811
2ios1双鱼座2631
3android1双鱼座2322
1ios0处女座1741
9ios0射手座4791
5ios1射手座672
4ios1水瓶座571
7ios1狮子座681
8ios1狮子座192
10ios1白羊座2551

可以很清晰的看到按星座分组,每个星座内部的PV排名的id。例如,射手座用户id9排名第一,用户id5排名第二。

  • 拓展使用:
  1. 更深一步的需求是筛出每个星座最高pv的用户,(或者说按星座去重,只取最高访问pv的用户)

  2. 再更进一步还可以计算诸如最大在线天数等SQL问题。

  3. 业务中常用用法为通过指定主键进行数据去重。

2.2 rank

  • 功能

按照指定列进行排名,如果值相同,则排名并列,下一个排名会出现跳跃,即排名是不连续的。例如有前2个值一样,那么前2行并列第一,第3行的排名则为3。

  • 示例

按使用客户端分组,统计年龄由高到低的排名。

select id,client,age,rank() over(partition by client order by age desc) as rank_id
from temp.user_info where id <= 10

数据结果:

idclientagerank_id
3android351
6ios361
5ios332
9ios323
4ios323
1ios295
7ios295
8ios287
2ios268
10ios268

可以看到上述信息中,通过安卓和iOS客户端的年龄大小排名。其中32岁两个并列第三,没有第四名,直接开始第五名。相同值进行并列。rank_id的排名是不连续的。

  • 拓展使用:

常用于指定排名场景

2.3 dense_rank

  • 功能

该函数可以和rank()对照使用,按照指定列排序的顺序输出窗口中的数据的排名,**如果值相同时,排名并列,下一个排名是连续递增的,不会出现跳跃情况。**即如果前2行的值相同,则前2行并列第1,第3行的排名则为第2。

可以理解为一个为疏松排名(rank),一个为密集排名(dense_rank)

  • 示例

按使用客户端分组,统计年龄由高到低的排名。

select id,client,age,dense_rank() over(partition by client order by age desc) as rank_id
from temp.user_info where id <= 10

数据结果:对比上文

idclientagerank_id
3android351
6ios361
5ios332
9ios323
4ios323
1ios294
7ios294
8ios285
2ios266
10ios266

可以看到,排名没有出现跳跃,是连续的,相同排名并列其名次。例如ios的32岁两个并列第三老。

  • 拓展使用

和rank相反,我希望出现不中断的排名,这样的使用场景。

2.4 percent_rank

  • 功能

见名知意,按百分比进行排名。

与 percent 函数类似,percent_rank (分布函数)函数的窗口 order by 子句所指定列中的值的返回值,是介于 0 和 1 之间的小数形式表示。

  • 计算方法

(rank - 1) / (n - 1)

rank为上述rank()函数的排名,n 为当前窗口的总数。

  • 示例

按使用客户端分组,统计年龄由高到低的百分比排名(percent_rank)。

另一种问法:某某用户的年龄(或者其他指标)在ios客户端排名前百分之多少?

select id,client,age,percent_rank() over(partition by client order by age desc) as rank_id
from temp.user_info where id <= 10

数据结果:

idclientagerank_id
3android350.0
6ios360.0
5ios330.125
9ios320.25
4ios320.25
1ios290.5
7ios290.5
8ios280.75
2ios260.875
10ios260.875

可以看出,用户9和4的年龄32岁排名ios客户端前百分之二十五,其并列排名。

  • 拓展使用

该函数经常用于较大数据量的百分比占比分析,也常用于探究数据分布分析场景。

例如可以通过分布函数踢除极值,进而求解均值,降低数据误差。

2.5 cume_dist

  • 功能

如果按升序排列,则统计:小于等于当前值的行数所占当前分区窗口总行数的比例。(number of rows ≤ current row)/(total number of rows)。

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

  • 示例

1.统计小于等于当前年龄的人数占总人数的比例。

另一种问法:小于等于29岁的人占总人数的比例。

select id,client,age,cume_dist() over(order by age desc) as rank_id
from temp.user_info where id <= 10
order by age

数据结果:

idclientagerank_id
2ios260.2
10ios260.2
8ios280.3
1ios290.5
7ios290.5
4ios320.7
9ios320.7
5ios330.8
3android350.9
6ios361.0

可以看到小于等于29岁所占人群的总比例为50%。

2.统计当前客户端分区小于等于当前年龄的人数占总人数的比例。

另一种问法:ios客户端小于等于29岁的人占总人数的比例。

select id,client,age,cume_dist() over(partition by client order by age) as rank_id
from temp.user_info where id <= 10
order by age

数据结果:

idclientagerank_id
2ios260.2222222222222222
10ios260.2222222222222222
8ios280.3333333333333333
1ios290.5555555555555556
7ios290.5555555555555556
4ios320.7777777777777778
9ios320.7777777777777778
5ios330.8888888888888888
3android351.0
6ios361.0

可以看到ios客户端小于等于29岁的人群占比为55.6%左右。

  • 拓展使用

该函数是一个累积求比例的函数,常用于求解排名前百分之多少或者排名后百分之多少的问题。

2.6 ntile

  • 功能

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

  • 注意

ntile不支持rows between,range between.

  • 示例

统计按照客户端分组,按年龄排序,将每个窗口分成3片(桶),返回每片(桶)的的分片(桶)信息。

另一种问法:把ios客户端的人群按年龄正序分成三部分,返回任意一部分的值。

select id,client,age,cume_dist() over(partition by client order by age) as rank_id
from temp.user_info where id <= 10
order by age

数据结果:

idclientagerank_id
3android351
10ios261
2ios261
8ios281
7ios292
1ios292
4ios322
9ios323
5ios333
6ios363

可以看到ios客户端9人被分为三部分,需要哪一部分,只要再限制rank_id 等于几就行。

  • 拓展使用

该函数是一个分桶函数,可以按照指定的列把数据均匀的分成想要的几部分数据。

例如,求解用户活跃时长前百分之二十的群体,如果包含0活跃时长用户,用百分比排序就不好计算了,而用该函数可以很快计算出来。

以上,为本次分享内容。

后续计划会开启一个新的系列内容:SQL每日一题系列,多来自各大厂的高频面试题,有好的算法面试题也可以积极分享,互相交流。

感谢阅读。

下一期:hive窗口分析函数使用详解之三-求偏移量类窗口函数

按例,欢迎点击此处关注我的个人公众号,交流更多知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/813854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在seata中编写测试用例

title: 如何在seata中编写测试用例 keywords: [Seata, unit test, junit, mockito, assertj] description: 这篇文章主要介绍了Seata中已经使用的测试用例相关框架&#xff0c;以及社区建议开发者如何更好的编写测试用例 author: 汪忠祥 - trustdecision 技术专家 date: 2024-0…

SecureCRT通过USB-Servial ch340串口无法连接单片机

通过USB To TTL连线 STM32F103-PRO&#xff0c;烧制程序到单片机上&#xff0c;通过SecureCRT通过USB-Servial ch340串口无法链接RS232升USB转TTL连接正确 开发板连接正确 问题&#xff1a;SecureCRT串口连接没有反应 问题分析&#xff1a;1、检查ch340串口驱动 查看设备管…

TQZC706开发板教程:在ZC706上运行ADRV9371(vivado2018.3)

首先需要在github上下载两个文件&#xff0c;本例程用到的文件以及最终文件&#xff0c;我都会放在网盘里面&#xff0c;地址在本文的末尾&#xff0c;需要自行提取 在github上搜索hdl选择第一个-->选择版本-->我所使用的vivado是2018.3版本&#xff0c;所以这里我下载的…

软考 - 系统架构设计师 - 面向对象架构设计案例

问题1&#xff1a; 解决该题&#xff0c;用例和参与者要一起进行分析&#xff0c;首先看到用例 U1 和 U2 是 U3 的扩展&#xff0c;分析用例列表中的用例&#xff0c;可以分析出 U1 和 U2 是Underpaid transaction 和 Record lllegal use&#xff0c;顺序可以颠倒&#xff0c;…

分享 GoLand 2024.1 激活的方案,支持JetBrains全家桶

大家好&#xff0c;欢迎来到金榜探云手&#xff01; GoLand 公司简介 JetBrains 是一家专注于开发工具的软件公司&#xff0c;总部位于捷克。他们以提供强大的集成开发环境&#xff08;IDE&#xff09;而闻名&#xff0c;如 IntelliJ IDEA、PyCharm、和 GoLand等。这些工具被广…

【QT学习】6.控件进阶,C与C++的强制类型转换,自定义控件,qt制作一个简易播放器

1.C与C的强制类型转换 2.自定义控件 要求&#xff1a;制作一个登录页面 1.使用控件拖拽一个页面出来 使用水平布局&#xff0c;垂直布局&#xff0c;网格布局 2.建立自定义控件 1.为项目添加自定义的类 自己写一个控件 2. &#xff08;1&#xff09;创建一个Group Box容器 &a…

springboot整合shiro之——拦截路径

简介Shiro: 1.基本功能 身份认证、授权、加密、会话管理 Web支持、缓存、多线程、测试、允许一个用户假装为另一个用户的身份进行访问、记住我 2. 执行过程 分为五步&#xff1a; Subject 用户主体&#xff1a;请求的发起者&#xff0c;即访问应用的用户 Security Manager 安…

xxl-job调度任务原理解析

xxljob可以对定时任务进行调度&#xff0c;现在看下定时任务调度的过程。XxlJobAdminConfig实现了InitializingBean接口&#xff0c;spring会调用afterPropertiesSet()进行初始化。大致有以下几个过程&#xff1a; admin服务端初始化 JobTriggerPoolHelper.java#toStart()方法…

1.Hexo安装和环境搭建引导

Hexo是一个依赖于一个名为nodejs的程序 因此安装它的方式在Mac和Windows上实际上是一样的 为了在电脑上安装Hexo 需要做两件事 nodejs&#xff0c;基本上是hexo依赖运行的JavaScript框架 Node.js — Run JavaScript Everywheregit&#xff0c;是一个程序&#xff0c;用来管理电…

Traefik和HAProxy全方位对比

在面对各种现代应用部署需求时&#xff0c;选择合适的反向代理和负载均衡器至关重要。Traefik&#x1f6a6;和HAProxy&#x1f6e1;️都是领先的解决方案&#xff0c;但它们各有特点&#xff0c;适用于不同的场景。本文将从多个维度全面对比Traefik&#x1f6a6;和HAProxy&…

【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 类的6个默认成员函数 构造函数 概念 构造函数的特性及用法 析构函数 概念 析构函数的特性及用法 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的构造函…

设计模式——外观(门面)模式10

外观模式&#xff1a;能为系统框架或其他复杂业务流程封装提供一个简单的接口。 例如抽奖过程中 设计模式&#xff0c;一定要敲代码理解 调用1&#xff08;抽奖系统&#xff09; /*** author ggbond* date 2024年04月08日 10:34*/ public class Lottery {public String getId…

OpenHarmony南向开发案例:【智能门锁】

一. 简介 本demo是基于Openharmony 3.1 Beta本版开发&#xff0c;不仅可以接收数字管家应用下发的指令来控制门锁开启&#xff0c;而且还可以通过数字管家设置不同的开锁密码以及一次性密码&#xff0c;实现给临时用户一个临时密码&#xff0c;保证门户安全。当然除了开锁的功…

遍历列举俄罗斯方块的所有形状

以前玩俄罗斯方块的时候&#xff0c;就想过一个问题&#xff0c;为什么俄罗斯方块就这7种形状&#xff0c;还有没有别的形状&#xff1f;自己也在纸上画过&#xff0c;比划来比划去&#xff0c;确实就这几种形状。 继续思考一下&#xff0c;那假如是3个块组合的形状&#xff0…

网页input框自动填充问题

autocomplete 大部分查询解决办法是设置&#xff0c;autocompleteoff&#xff0c;关于autocomplete的含义&#xff0c;官网参考如下: HTML attribute: autocomplete - HTML: HyperText Markup Language | MDN 在 autocomplete 的文档中说明了 value 为 off 时&#xff0c;浏览…

双子座 Gemini1.5和谷歌的本质

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

游戏软件测试流程

备注:本文为博主原创文章,未经博主允许禁止转载。如有问题,欢迎指正。 个人笔记(整理不易,有帮助,收藏+点赞+评论,爱你们!!!你的支持是我写作的动力) 笔记目录:学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 个人随笔:工作总结随笔_8、…

【STL】list

目录 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1.3 list capacity 1.4 list element access 1.5 list modifiers 1.6 list的迭代器失效 2. list的模拟实现 3. list与vector的对比 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1. begin与end为…

JavaEE初阶Day 6:多线程(4)

目录 Day 6&#xff1a;多线程&#xff08;4&#xff09;1. 线程不安全的原因2. 锁3. synchronized Day 6&#xff1a;多线程&#xff08;4&#xff09; 前序&#xff1a;针对Day 5结尾的count 多线程的执行&#xff0c;是随机调度抢占式的执行模式&#xff0c;某个线程执行指…

KVM + GFS 分布式存储

目录 一、案例分析 1.1、案例概述 1.2、案例前置知识点 1&#xff09;Glusterfs 简介 2&#xff09;Glusterfs 特点 1.3、案例环境 1&#xff09;案例环境 2&#xff09;案例需求 3&#xff09;案例实现思路 二、案例实施 2.1、安装部署 KVM 虚拟化平台 1&…