hive-窗口函数

1 窗口函数语法

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

常用的分析函数

常用的分析函数:sum()、max()、min()、avg()、count()

常用的专用窗口函数

专用窗口函数:row_number()、rank()、dense_rank()

窗口函数

窗口函数的3个组成部分可以单独使用,也可以混合使用,也可以全部不用

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

partition by

对指定的字段进行分组,后续都会以组为单位,把每个分组单独作为一个窗口进行统计分析操作。

案例 01:对窗口中的数据求和,并把求和结果分别分发到对应窗口的每一条数据中

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1) as '对窗口中的数据求和'
from temp
输出结果:
col     对窗口中的数据求和
A       2
A       2
B       1

案例 02:对整体数据求和,并把求和结果分发到每一条数据中

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over() as '对整体数据求和'
from temp
输出结果:
col     对整体数据求和
A       3
A       3
B       3

order by

order by 与 partition by 连用的时候,可以对各个分组内的数据,按照指定的字段进行排序。如果没有 partition by 指定分组字段,那么会对全局的数据进行排序。

案例 01:对数据进行全局排序

with temp as(
select 'A' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,row_number() over(order by col1 desc) as 排序 from temp
输出结果:
col1     排序 
C        1
C        2
B        3
A        4

案例 02:当排序的维度不存在重复的情况下,即 order by 指定的字段,使用 order by + 分析函数 sum(),可以产生求整体累计数的效果。

with temp_01 as(
select 'A' as col1,1 as col2
union all 
select 'D' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,sum(col2) over(order by col1) as 求累计 from temp_01
输出结果:
col1    求累计
A       1
B       2
C       3
D       4

但是当 order by 指定的字段,数据存在重复的时候,会在不重复的数据中产生累计效果,重复的数据中,会把整体的累计结果分发到每条重复的数据中。

with temp_02 as(
select 'A' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'C' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select col1,sum(col2) over(order by col1) as 求累计 from temp_02
输出结果:
col1    求累计
A       1
B       2
C       4
C       4

案例 03:当排序的维度不存在重复的情况下,即 order by 指定的字段,parition by 与 order by 连用,并使用分析函数 sum() ,可以产生求窗口中累计数的效果。

with temp_01 as(
select 'A' as col1,'b' as col2,1 as col3
union all 
select 'A' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'b' as col2,1 as col3
)select col1,sum(col3) over(partition by col1 order by col1,col2) as 求累计 from temp_01
输出结果:
col1     求累计
A        1
A        2
C        1
C        2

但是当 order by 指定的字段组合,数据存在重复的时候,会在不重复的数据中产生累计效果,而重复的数据中,也是会把整体的累计结果分发到每条重复的数据中,如下,用 col1 和 col2 排序。

with temp_02 as(
select 'A' as col1,'b' as col2,1 as col3
union all 
select 'A' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
union all 
select 'C' as col1,'a' as col2,1 as col3
)select col1,sum(col3) over(partition by col1 order by col1,col2) as 求累计 from temp_02
输出结果:
col1     求累计
A        1
A        2
C        2
C        2

rows between 开始位置 and 结束位置

rows between 是用来划分窗口中,函数发挥作用的数据范围。我们用如下例子加深 rows between 的理解。
在这里插入图片描述

在A分组中,计算第2行,第2列的值的时候,会从窗口起点(第2行,第2列),计算到当前行(第2行,第2列)。结果是1。
在A分组中,计算第3行,第2列的值的时候,会从窗口起点(第2行,第2列),计算到当前行(第3行,第2列)。结果是2。

rows between 常用的参数如下:

① n preceding:往前

② n following:往后

③ current row:当前行

④ unbounded:起点(一般结合preceding,following使用)

a. unbounded preceding:表示该窗口最前面的行(起点) b. unbounded
following:表示该窗口最后面的行(终点)

使用例子如下:

rows between unbounded preceding and current row(表示从起点到当前行的数据进行) rows
between current row and unbounded following(表示当前行到终点的数据进行) rows
between unbounded preceding and unbounded following (表示起点到终点的数据) rows
between 1 preceding and 1 following(表示往前1行到往后1行的数据) rows between 1
preceding and current row(表示往前1行到当前行)

rows between unbounded preceding and current row与 partition by 、order by 连用,可以产生对窗口中的数据求累计数的效果。

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1 order by col2 desc rows between unbounded preceding and current row) as '对窗口中的数据求和'
from temp
输出结果:
col1     对窗口中的数据求和
A        1
A        2
B        1
  1. 排序窗口函数
    2.1 排序并产生自增编号,自增编号不重复且连续
    我们可以使用函数:row_number() over()

数据样例:

col1                             ranks
a            1
b              2
b              3
b              4
c              5
d              6具体语法如下:> row_number() over(partition by 列名 order by 列名 rows between 开始位置 and
> 结束位置)案例如下:>with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)
>
>select col1,row_number() over(order by col1) as ranks from temp
输出结果:
col1     rank
a        1
b        2
b        3
b        4
c        5
d        6

2.2 排序并产生自增编号,自增编号会重复且不连续
我们可以使用函数:rank() over()

数据样例:

col1     ranks
a        1
b        2
b        2
b        2
c        5
d        6

具体语法如下:

rank() over(partition by 列名 order by 列名 rows between 开始位置 and 结束位置)

案例如下:

with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)select col1,rank() over(order by col1) as ranks from temp
输出结果:
col1     rank
a        1
b        2
b        2
b        2
c        5
d        6

2.3 排序并产生自增编号,自增编号会重复且连续
我们可以使用函数:dense_rank() over()

数据样例:

col1     ranks
a        1
b        2
b        2
b        2
c        3
d        4

具体语法如下:

dense_rank() over(partition by 列名 order by 列名 rows between 开始位置 and
结束位置)

案例如下:

with temp as(
select 'a' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'b' as col1
union all 
select 'c' as col1
union all 
select 'd' as col1
)select col1,dense_rank() over(order by col1) as ranks from temp	
输出结果:
col1     ranks
a        1
b        2
b        2
b        2
c        3
d        4

聚合窗口函数

3.1 求窗口中的累计值
我们可以使用:sum() over()

with temp as(
select 'A' as col1,1 as col2
union all 
select 'A' as col1,1 as col2
union all
select 'A' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
union all 
select 'B' as col1,1 as col2
)select
col1
,sum(col2) over(partition by col1 order by col2 desc rows between unbounded preceding and current row) as '对窗口中的数据求和'
from temp
输出结果:
col1     对窗口中的数据求和
A        1
A        2
A        3
B        1
B        1

3.2 求窗口中 3 天的平均价格
我们可以使用 avg() over()

with temp as(
select 'A' as col1,'2022-11-01' as date_time,50 as price
union all 
select 'A' as col1,'2022-11-02' as date_time,60 as price
union all 
select 'A' as col1,'2022-11-03' as date_time,45 as price
union all 
select 'A' as col1,'2022-11-04' as date_time,70 as price
union all 
select 'A' as col1,'2022-11-05' as date_time,40 as price
union all 
select 'A' as col1,'2022-11-06' as date_time,40 as price
union all 
select 'B' as col1,'2022-11-01' as date_time,40 as price
union all 
select 'B' as col1,'2022-11-02' as date_time,30 as price
union all 
select 'B' as col1,'2022-11-03' as date_time,50 as price
union all 
select 'B' as col1,'2022-11-04' as date_time,50 as price
)select
col1
,date_time
,price
,avg(price) over(partition by col1 order by date_time rows between 2 preceding and current row) as '3天的平均价格'
from temp输出结果:
col1      date_time        price      3天的平均价格
A         2022-11-01       50         50
A         2022-11-02       60         55
A         2022-11-03       45         51.666666666666664
A         2022-11-04       70         58.333333333333336
A         2022-11-05       40         51.666666666666664
A         2022-11-06       40         50
B         2022-11-01       40         40
B         2022-11-02       30         35
B         2022-11-03       50         40
B         2022-11-01       50         43.333333333333336

3.3 求分组中的最大值/最小值

with temp_01 as(
select 'A' as col1,10 as col2
union all 
select 'C' as col1,10 as col2
union all 
select 'C' as col1,20 as col2
union all 
select 'A' as col1,20 as col2
union all
select 'A' as col1,20 as col2
)select
col1
,col2
,max(col2) over(partition by col1) as 窗口中的最大值
,min(col2) over(partition by col1) as 窗口中的最小值
from temp_01输出结果:
col1     col2     窗口中的最大值     窗口中的最小值
A        10       20                 10
A        20       20                 10
A        20       20                 10
C        10       20                 10
C        20       20                 10

3.4 求分组中的总记录数

with temp_01 as(
select 'A' as col1,'a' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'A' as col1,'b' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,col2
,count(col2) over(partition by col1) as 分组中的记录数
from temp_01输出结果:
col1     col2     分组中的记录数
A        a        3
A        b        3
A        b        3
C        a        2
C        a        2
  1. 位移窗口函数
    4.1 获取分组中往前 n 行的值
    基础语法:

lead(field,n,default_value) over()

语法解析:

  1. field 是指定的列名

  2. n 是往前的行数

  3. 行往前导致的,最后的 n 行值为 null,可以用 default_value 代替。

使用案例:

with temp_01 as(
select 'A' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-02' as date_time
union all 
select 'A' as col1,'2022-12-02' as date_time
union all
select 'A' as col1,'2022-12-03' as date_time
)select
col1
,date_time
,lead(date_time,1,'2022-12-30') over(partition by col1 order by date_time) as 往前n行的值 
from temp_01输出结果:
col1     date_time     往前n行的值
A        2022-12-01    2022-12-02
A        2022-12-02    2022-12-03
A        2022-12-03    2022-12-30
C        2022-12-01    2022-12-02
C        2022-12-02    2022-12-30

4.2 获取分组中往后 n 行的值
基础语法:

lag(field,n, default_value) over()

语法解析:

  1. field 是指定的列名

  2. n 是往前的行数

  3. 行往后导致的,前面的 n 行值为 null,可以用 default_value 代替。

使用案例:

with temp_01 as(
select 'A' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-01' as date_time
union all 
select 'C' as col1,'2022-12-02' as date_time
union all 
select 'A' as col1,'2022-12-02' as date_time
union all
select 'A' as col1,'2022-12-03' as date_time
)select
col1
,date_time
,lag(date_time,1,'2022-12-30') over(partition by col1 order by date_time) as 往前n行的值 
from temp_01输出结果:
col1      date_time     往前n行的值
A         2022-12-01    2022-12-30
A         2022-12-02    2022-12-01
A         2022-12-03    2022-12-02
C         2022-12-01    2022-12-30
C         2022-12-02    2022-12-01

极值窗口函数

5.1 获取分组内第一行的值
我们可以使用 first_value(col,true/false) over(),作用是:取分组内排序后,截止到当前行,第一个值。

注意:

当第二个参数为 true 的时候,会跳过空值 当 over() 中不指定排序的时候,会默认使用表中数据的原排序。
案例:将每行数据换成当前窗口指定字段的第一个值

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,first_value(col2) over(partition by col1 order by col2) as 第一个值 
from temp_01
输出结果:
col1     第一个值
A        a
A        a
A        a
C        a 
C        a
select
col1
,first_value(col2) over(partition by col1) as 第一个值 
from temp_01
输出结果:
col1     第一个值
A        b
A        b
A        b
C        a
C        a

5.2 获取分组内最后一行的值
我们可以使用 last_value(col,true/false) over(),作用是:取分组内排序后,截止到当前行,最后一个值。所以,如果使用 order by 排序的时候,想要取最后一个值,需要与 rows between unbounded preceding and unbounded following 连用。

注意:

当第二个参数为 true 的时候,会跳过空值 当 over() 中不指定排序的时候,会默认使用表中数据的原排序。 当 over()
中指定排序的时候,要与 rows between unbounded preceding and unbounded following
连用

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,last_value(col2) over(partition by col1 order by col2 rows between unbounded preceding and unbounded following) as 第一个值 
from temp_01输出结果:
col1       第一个值
A          b
A          b
A          b
C          b
C          b

相信大家都发现了,在本案例中,我们使用 order by 的时候与 rows between unbounded preceding and unbounded following 连用了,这是需要注意的一个点,如果不连用,将会产生以下效果:

with temp_01 as(
select 'A' as col1,'b' as col2
union all 
select 'C' as col1,'a' as col2
union all 
select 'C' as col1,'b' as col2
union all 
select 'A' as col1,'a' as col2
union all
select 'A' as col1,'b' as col2
)select
col1
,last_value(col2) over(partition by col1 order by col2) as 第一个值 
from temp_01输出结果:
col1      第一个值
A         a
A         b
A         b
C         a
C         b
  1. 分箱窗口函数
    ntile() over() 分箱窗口函数,用于将分组数据按照顺序切分成 n 片,返回当前切片值,如果切片不均匀,默认增加到第一个切片中。

案例:查询成绩前 20% 的人。

with temp as(
select 'A' as col1,90 as grade
union all 
select 'B' as col1,80 as grade
union all
select 'C' as col1,82 as grade
union all
select 'D' as col1,99 as grade
union all 
select 'E' as col1,100 as grade
union all 
select 'F' as col1,92 as grade
union all
select 'G' as col1,93 as grade
union all
select 'H' as col1,85 as grade
union all
select 'I' as col1,95 as grade
union all
select 'J' as col1,70 as grade
)select 
col1
,grade
from(selectcol1,grade,ntile(5) over(order by grade desc) as levelfrom temp)t1
where t1.level = 1输出结果:
col1     grade
E        100
D        99

转载:https://zhuanlan.zhihu.com/p/587440793

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

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

相关文章

【简易版】Linux下Protobuf 实现网络版通讯录--C++

一、介绍 该项目的主要目的是用于熟悉protobuf的使用,体验数据在网络中序列化反序列化的形式,并非一个完整的项目。 该通讯录只实现了增加联系人的功能。服务器端接收到请求后会将联系人的信息打印。 二、环境搭建 使用Httplib库,可以快速…

jsp文件引用的css修改后刷新不生效问题

问题 在对 JavaWeb 项目修改的过程中,发现修改了 jsp 文件引入的 css 文件的代码后页面的样式没有更新的问题。 原因 导致这个问题的原因可能是因为浏览器缓存的问题。 解决方法 下面介绍两种解决方法,供大家参考: 1、给 link 标签的 c…

TrustZone之安全虚拟化

在Armv7-A首次引入虚拟化时,它仅在非安全状态中添加。在Armv8.3之前,Armv8也是如此,如下图所示: 如前所述在切换安全状态时,EL3用于托管固件和安全监视器。安全EL0/1托管受信任的执行环境(TEE),由受信任的服务和内核组成。 在安全状态下,没有对多个虚拟机的需…

Kafka生产问题总结及性能优化实践

1、消息丢失情况 消息发送端: (1)acks0: 表示producer不需要等待任何broker确认收到消息的回复,就可以继续发送下一条消息。性能最高,但是最容易丢消息。大数据统计报表场景,对性能要求很高&am…

JavaCV之rtmp推流(FLV和M3U8)

JavaCV与FFmpeg FFmpeg是一款开源的多媒体处理工具集,它包含了一系列用于处理音频、视频、字幕等多媒体数据的库和工具。 JavaCV集成了FFmpeg库,使得Java开发者可以使用FFmpeg的功能,比如视频解码、编码、格式转换等。 除了FFmpeg&#xff0…

LeetCode力扣每日一题(Java):35、搜索插入位置

一、题目 二、解题思路 1、我的思路(又称:论API的重要性) 读完题目之后,我心想这题目怎么看着这么眼熟?好像我之前学过的一个API呀! 于是我回去翻了翻我之前写的博客:小白备战蓝桥杯&#xf…

通用的AGI 安全风险

传统安全风险 平台基础设施安全风险 模型与数据层安全风险 应用层安全风险 平台基础设施安全风险 (1)物理攻击:机房管控不到位 (2)网络攻击 (3)计算环境:自身安全漏洞&#xf…

编辑器Sublime text 常用快捷命令 列模式 替换空行

平替notepad 下载可取官网 www.sublimetext.com 据说可以无限试用,没有功能限制 1、快速删除空行 ctrl h选择正则表达式 .*Find输入: ^(\t)*$\nReplace输入:点击Replace All 2、快速选择指定字符 用鼠标选中alt f3修改 3、列编辑模式 ct…

宇视科技视频监控 main-cgi 文件信息泄露漏洞复现

0x01 产品简介 宇视(Uniview)高清网络摄像机是一种高性能的网络摄像机,它可以通过网络进行视频传输和监控。该摄像机采用先进的视频技术,具有高清晰度、低照度、宽动态等特点,能够提供高质量的视频图像。 0x02 漏洞概述 宇视(Uniview)高清网络摄像机存在信息泄露漏洞…

ppt编辑密码如何设置?

大家在PPT中设置了限制编辑,发现后面任然可以编辑文件。那么如何将PPT文件设置成禁止修改模式呢?今天分享几个方法给大家。 方法一 将PPT文件直接保存或者另存为一份文件,在保存时,将文件格式选择为PowerPoint图片演示文稿 方法…

.NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(测试篇)

WebAppDbTest 项目测试 测试工具 ltt介绍安装使用方式1、Drill2、Hammer3、Nailgun 测试主机规格配置CRUD 性能测试对比1、ltt 工具测试1.1、AddSingle 单条数据添加1.2、AddBulk 批量数据(1000)条添加1.3、GetSingle 单条数据查询1.4、GetAll 多条&…

多合一iPhone 解锁工具:iMyFone LockWiper iOS

多合一iPhone 解锁工具 无需密码解锁 iPhone/iPad/iPod touch 上所有类型的屏幕锁定 在几分钟内解锁 iPhone Apple ID、Touch ID 和 Face ID 立即绕过 MDM 并删除 iPhone/iPad/iPod touch 上的 MDM 配置文件 支持所有 iOS 版本和设备,包括最新的 iOS 17 和 iPhone 1…

JAVA实操经验

零: 按照需要,可以使用需要某个类下(主要是java提供的)的方法来实现某个功能。(主要是用在不同类下的方法会进行重写功能不同) 方法和构造方法不同:方法是方法,构造方法是构造器&a…

基于FPGA的视频接口之高速IO

简介 相对于其他视频接口来说,高速IO接口(以Xilinx公司为例,spartan 6系列的GTP、Artix7系列的GTP,KENTEX7系列的GTX和GTH等)具有简化设计、充分利用FPGA资源、降低设计成本等功能。 高速IO接口传输视频,一般会被拓展为万兆以太网、40G以太网、10G光纤、40G光纤、3G-SDI、…

c语言插入排序及希尔排序详解

目录 前言: 插入排序: 希尔排序: 前言: 排序在我们生活中无处不在,比如学生成就排名,商品价格排名等等,所以排序在数据结构的学习中尤为重要,今天就为大家介绍两个经典的排序算法&…

深入解析C++中的虚函数和虚继承:实现多态性与继承关系的高级特性

这里写目录标题 虚函数虚函数实现动态绑定虚继承抽象类 虚函数 虚函数是在C中用于实现多态性的一种特殊函数。它通过使用关键字"virtual"进行声明,在基类中定义,可在派生类中进行重写。虚函数允许在运行时根据对象的实际类型来调用相应的函数…

BigData之Google Hadoop中间件安装

前言 Hadoop / Zookeeper / Hbase 因资源有限 这三个都是安装在同一台Centos7.9的机器上 但通过配置 所以在逻辑上是distributed模式 1 Java安装 1.1 下载java11 tar/opt/java/jdk-11.0.5/ 1.2 环境配置修改 文件/etc/profile export JAVA_HOME/opt/java/jdk-11.0.5/ e…

HarmonyOS编译开源native库(OpenSSL实例)

前言 近期项目要开始做鸿蒙版本,有一部分依赖native的代码也需要迁移,某个native模块依赖openssl,需要在鸿蒙下重新编译openssl才行。一开始找了很多相关文档都没有得到方法,无奈只能自己凭经验慢慢试,最后还是成功了…

JS基础之执行上下文

JS基础之执行上下文 执行上下文顺序执行可执行代码执行上下文栈回顾上文 执行上下文 顺序执行 写个JavaScript的开发者都会有个直观的印象,那就是顺序执行: var foo function(){console.log(foo1) } foo(); //foo1 var foo function(){console.log(…

HTML面试题---专题一

文章目录 一、前言二、 HTML5 中 <header> 和 <footer> 标签的用途是什么&#xff1f;三、如何在 HTML 中嵌入 SVG&#xff08;可缩放矢量图形&#xff09;文件&#xff1f;四、解释 contenteditable 属性的用途五、如何创建随屏幕尺寸缩放的响应式图像&#xff1f…