hiveSQL开窗函数详解

news/2024/5/8 12:07:04/文章来源:https://blog.csdn.net/weixin_62759952/article/details/129269434

hive开窗函数

文章目录

  • hive开窗函数
    • 1. 开窗函数概述
      • 1.1 窗口函数分类
      • 1.2 窗口函数和普通聚合函数的区别
    • 2. 窗口函数的基本用法
      • 2.1 基本用法
      • 2.2 设置窗口的方法
        • 2.2.1 window_name
        • 2.2.2 partition by
        • 2.2.3 order by 子句
        • 2.2.4 rows指定窗口大小
          • 窗口框架
      • 2.3 开窗函数中加 order by 和不加 order by 的区别
    • 3. 窗口函数用法举例
      • 3.1 序号函数: row_number() / rank() / dese_rank()
      • 3.2 分布函数: percent_rank() / cume_dist()
        • 3.2.1 percent_rank()
        • 3.2.2 cume_dist()
        • 3.2.3 前后函数lag(expr, n, defval) 、 lead(expr, n, defval)
        • 3.2.4 头尾函数:first_value(expr) 、 last_value(expr)
    • 4 聚合函数+窗口函数

1. 开窗函数概述

窗口函数也称OLAP函数,对数据库进行实时分析处理

1.1 窗口函数分类

  • 序号函数:row_number() / rank() / dense_rank()
  • 分布函数:percent_rank() / cume_dist()
  • 前后函数:lag() / lead()
  • 头尾函数:first_val() / last_val()
  • 聚合函数+窗口函数:sum() over()、 max()/min() over() 、avg() over()
  • 其他函数:nth_value() / nfile()

1.2 窗口函数和普通聚合函数的区别

聚合函数是将多条记录聚合成一条,窗口函数是每条记录都会执行,有几条记录执行完还是几条

窗口函数兼具group by子句的分组功能和order by子句的排序功能,但是partition by 子句不具备group by的汇总功能

2. 窗口函数的基本用法

准备基础数据

CREATE TABLE exam_record (uid int COMMENT '用户ID',exam_id int COMMENT '试卷ID',start_time timestamp COMMENT '开始时间',submit_time timestamp COMMENT '提交时间',score tinyint COMMENT '得分'
) 
COMMENT '考试记录表'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
TBLPROPERTIES ("skip.header.line.count"="1");INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:02', 84),
(1006, 9001, '2021-09-01 12:11:01', '2021-09-01 12:31:01', 89),
(1006, 9002, '2021-09-06 10:01:01', '2021-09-06 10:21:01', 81),
(1005, 9002, '2021-09-05 10:01:01', '2021-09-05 10:21:01', 81),
(1005, 9001, '2021-09-05 10:31:01', '2021-09-05 10:51:01', 81),
(1004, 9002, '2021-09-05 10:01:01', '2021-09-05 10:21:01', 71),
(1004, 9001, '2021-09-05 10:31:01', '2021-09-05 10:51:01', 91),
(1004, 9002, '2021-09-05 10:01:01', '2021-09-05 10:21:01', 80),
(1004, 9001, '2021-09-05 10:31:01', '2021-09-05 10:51:01', 80);select * from exam_record;
exam_record.uid	exam_record.exam_id	exam_record.start_time	exam_record.submit_time	exam_record.score
1006	9001	2021-09-01 12:11:01	2021-09-01 12:31:01	89
1006	9002	2021-09-06 10:01:01	2021-09-06 10:21:01	81
1005	9002	2021-09-05 10:01:01	2021-09-05 10:21:01	81
1005	9001	2021-09-05 10:31:01	2021-09-05 10:51:01	81
1004	9002	2021-09-05 10:01:01	2021-09-05 10:21:01	71
1004	9001	2021-09-05 10:31:01	2021-09-05 10:51:01	91
1004	9002	2021-09-05 10:01:01	2021-09-05 10:21:01	80
1004	9001	2021-09-05 10:31:01	2021-09-05 10:51:01	80

2.1 基本用法

窗口函数语法

<窗口函数> over[(partition by <列表清单>)] order by <排序列表清单> [rows between 开始位置 and 结束位置]

窗口函数:指要使用的分析函数,

over(): 用来指定窗口函数的范围,如果括号中什么都不写,则窗口包含where的所有行

select uidscore,sum(score) over() as sum_score
from exam_record;

运行结果

uid	score	sum_score
1006	89	654
1006	81	654
1005	81	654
1005	81	654
1004	71	654
1004	91	654
1004	80	654
1004	80	654

2.2 设置窗口的方法

2.2.1 window_name

给窗口指定一个别名

select uid,score,rank() over my_window_name as rk_num,row_number() over my_window_name as row_num
from exam_record
window my_window_name as (partition by uid order by score);

请添加图片描述

2.2.2 partition by

select uid,score,sum(score) over(partition by uid) as sum_score
from exam_record;

请添加图片描述

按照uid进行分组,分别求和

使用row_number()序号函数,表明序号

selectuid,score,row_number() over(partition by uid) as row_num
from exam_record;

请添加图片描述

2.2.3 order by 子句

按照哪些字段进行排序,窗口函数将按照排序后的记录进行编号

selectuid,score,row_number() over (partition by uid order by score desc) as row_num
from exam_record

请添加图片描述

单独使用order by uid

selectuid,score,sum(score) over (order by uid desc) as row_num
from exam_record;

请添加图片描述

单独使用partition by uid

selectuid,score,sum(score) over (partition by uid) as row_num
from exam_record;

请添加图片描述

partition by进行分组内的求和,分区间独立

order by 对序号相同的进行求和,对序号不同的进行累加求和

单独使用order by score

selectuid,score,sum(score) over (order by score desc) as row_num
from exam_record;

请添加图片描述

2.2.4 rows指定窗口大小

查看score的平均值

selectuid,score,avg(score) over(order by score desc) as avg_num
from exam_record

请添加图片描述

按照score降序排列,每一行计算前一行到当前行的score的平均值

selectuid,score,avg(score) over(order by row_score) as avg_num
from(selectuid,score,row_number() over(order by score desc) as row_scorefrom exam_record)res

请添加图片描述

窗口框架

指定窗口大小,框架是对窗口的进一步分区,框架有两种限定方式:

使用rows语句,通过指定当前行之前或之后的固定数目的行来限制分区中的行数

使用range语句,按照排列序列的当前值,根据相同值来确定分区中的行数

order by 字段名 range|rows 边界规则0 | [between 边界规则1] and 边界规则2 

range和rows的区别

range按照值的范围进行范围的定义,rows按照行的范围进行范围的定义

请添加图片描述

  • 使用框架时,必须要有order by子句,如果仅指定了order by子句未指定框架,则默认框架会使用range unbounded preceding and current row (从第一行到当前行的数据)
  • 如果窗口函数没有指定order by子句,就不存在 rows|range 窗口的计算
  • range 只支持使用unbounded 和 current row

查询我与前两名的平均值

selectuid,score,avg(score) over(order by score desc rows 2 preceding) as avg_score
from exam_record;

请添加图片描述

查询当前行及前后一行的平均值

selectuid,score,avg(score) over(order by score desc rows between 1 preceding and 1 following) as avg_score
from exam_record;

请添加图片描述

2.3 开窗函数中加 order by 和不加 order by 的区别

当开窗函数为排序函数时,如row_number()、rank()等,over中的order by 只起到窗口内排序的作用

当开窗函数为聚合函数时,如max、min、count等,over中的order by不仅对窗口内排序,还起到窗口内从当前行到之前所有行的聚合

selectuid,exam_id,start_time,sum(score) over(partition by uid) as one,sum(score) over(partition by uid order by start_time) as two
from exam_record

请添加图片描述

3. 窗口函数用法举例

3.1 序号函数: row_number() / rank() / dese_rank()

区别:rank() : 并列排序,跳过重复序号------1、1、3

​ row_number() : 顺序排序——1、2、3

​ dese_rank() : 并列排序,不跳过重复序号——1、1、2

selectuid,score,rank() over my_window as rk_num,row_number() over my_window as row_num
from exam_record
window my_window as (partition by uid order by score);

请添加图片描述

不使用窗口函数实现分数排序

SELECTP1.uid,P1.score,(SELECTCOUNT(P2.score)FROM exam_record P2WHERE P2.score > P1.score) + 1 AS rank_1
FROM exam_record P1
ORDER BY rank_1;

请添加图片描述

3.2 分布函数: percent_rank() / cume_dist()

3.2.1 percent_rank()

percent_rank() 函数将某个数据在数据集的排位作为数据集的百分比值返回,范围0到1,

按照(rank - 1) / (rows - 1)进行计算,rank为rank()函数产生的序号,rows为当前窗口的记录总行数

selectuid,score,rank() over my_window as rank_num,percent_rank() over my_window as prk
from exam_record
window my_window as (order by score desc)

请添加图片描述

3.2.2 cume_dist()

如果升序排列,则统计:小于等于当前值的行数 / 总行数

如果降序排列,则统计:大于等于当前值的行数 / 总行数

查询小于等于当前score的比例

selectuid,score,rank() over my_window as rank_num,cume_dist() over my_window as cume
from exam_record
window my_window as (order by score asc);

请添加图片描述

3.2.3 前后函数lag(expr, n, defval) 、 lead(expr, n, defval)

lag()和lead()函数可以在同一次查询中取出同一字段前 n 行的数据和后 n 行的数据作为独立列

lag( exp_str,offset,defval) over(partition by .. order by …)lead(exp_str,offset,defval) over(partition by .. order by …)
  • exp_str 是字段名
  • offset是偏移量,即 n 的值
  • defval默认值,如何当前行向前或向后 n 的位置超出表的范围,则会将defval的值作为返回值,默认为NULL

查询前1名同学和后一名同学的成绩和当前同学成绩的差值

  • 先将前一名、后一名以及当前行的分数放在一起
selectuid,score,lag(score, 1, 0) over my_window as `before`,lead(score, 1, 0) over my_window as `next`
from exam_record
window my_window as (order by score desc);

请添加图片描述

  • 然后做差值
selectuid,score,score - before as before,score - next as next
from (selectuid,score,lag(score, 1, 0) over my_window as before,lead(score, 1, 0) over my_window as next
from exam_record
window my_window as (order by score desc))res

请添加图片描述

3.2.4 头尾函数:first_value(expr) 、 last_value(expr)

  • 返回第一个expr:first_value(expr)
  • 返回第二个expr:last_value(expr)

查询第一个和最后一个分数

selectuid,score,first_value(score) over my_window as first,last_value(score) over my_window as last
from exam_record
window my_window as (order by score desc);

请添加图片描述

4 聚合函数+窗口函数

窗口函数在where之后执行,所以where需要用窗口函数作为条件

 SELECTuid,score,sum(score) OVER my_window_name AS sum_score,max(score) OVER my_window_name AS max_score,min(score) OVER my_window_name AS min_score,avg(score) OVER my_window_name AS avg_scoreFROM exam_recordWINDOW my_window_name AS (ORDER BY score desc)

请添加图片描述

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

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

相关文章

一文吃透 Spring 中的 AOP 编程

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【C++】二叉搜索树的模拟实现

一、概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左右子树也分别…

开源ZYNQ AD9361软件无线电平台

&#xff08;1&#xff09; XC7Z020-CLG400 &#xff08;2&#xff09; AD9363 &#xff08;3&#xff09; 单发单收&#xff0c;工作频率400MHz-2.7GHz &#xff08;4&#xff09; 发射带PA&#xff0c;最大输出功率约20dbm &#xff08;5&#xff09; 接收带LNA&#xff0c;低…

Linux学习(9.1)文件系统的简单操作

以下内容转载自鸟哥的Linux私房菜 原文&#xff1a;鸟哥的 Linux 私房菜 -- Linux 磁盘与文件系统管理 (vbird.org) 磁盘与目录的容量 df&#xff1a;列出文件系统的整体磁盘使用量&#xff1b;du&#xff1a;评估文件系统的磁盘使用量(常用在推估目录所占容量) df du 实体…

微信小程序 《新闻列表》 案例

目录&#xff1a;一&#xff0c;步骤。要求1&#xff1a;主页头部的轮播图要求2&#xff1a;中间内容上的信息案列排版。要求3&#xff1a;上拉加载内容。要求4&#xff1a;在信息加载完成后&#xff0c;给用户提示二&#xff0c;过程中要注意的几点。1.在微信小程序中&#xf…

HNU工训中心:电子开关与信号隔离

工训中心的牛马实验 1.实验目的&#xff1a; 1) 认识三极管和MOS管构成三端电子开关电路&#xff1b; 认识信号隔离的继电器和光电隔离方式。 2) 认识施密特触发器&#xff0c;掌握一种波形变换方法。 3) 实现一种脉冲波形发生器。 2.实验资源 HBE硬件基础电路实验箱、示波…

第八节 构造器和this关键字、封装

构造器的作用 定义在类中的&#xff0c;可以用于初始化一个类的对象&#xff0c;并返回对象的地址。 构造器的注意事项 1.任何类定义出来&#xff0c;默认就自带了无参数构造器&#xff0c;写不写都有。 2.一旦定义了有参数构造器&#xff0c;那么无参数构造器就没有了&#xf…

Adversarially-Aware Robust Object Detector

目标检测作为计算机视觉的基本任务&#xff0c;随着深度神经网络的出现而取得了显著的进展。然而&#xff0c;很少有研究在各种现实场景中探索目标检测器抵抗对抗攻击的对抗鲁棒性。探测器已经受到不可察觉的扰动的极大挑战&#xff0c;在干净图像上的性能急剧下降&#xff0c;…

记录pytorch安装 windows10 64位--(可选)安装paddleseg

安装完paddlepaddle之后&#xff0c;就可以安装paddleseg了。一、安装Git可以参考这个网址&#xff1a;https://blog.csdn.net/u010348546/article/details/124280236windows下安装git和gitbash安装教程二、安装paddleseghttps://github.com/PaddlePaddle/PaddleSeg记得翻墙啊这…

Ubuntu 交叉编译工具链安装

Ubuntu 交叉编译工具链安装 1 交叉编译器安装 ARM 裸机、Uboot 移植、Linux 移植这些都需要在 Ubuntu 下进行编译&#xff0c;编译就需要编译器&#xff0c;我们在第三章“Linux C 编程入门”里面已经讲解了如何在 Liux 进行 C 语言开发&#xff0c;里面使用 GCC 编译器进行代…

试题 算法训练 JOE的矩阵

问题描述 最近JOE又在线性代数的模拟考中拿满分了&#xff0c;这直接导致了JOE对于计算矩阵的热情急剧下降&#xff0c;所以JOE希望能有这样一个程序能帮助他计算矩阵的秩。 输入格式 第一行&#xff0c;两个数n,m&#xff0c;表示矩阵是n*m的。   下面共n行&#xff0c;每行…

Airbnb(三) Managing Diversity in Airbnb Search 搜索多样性

abstract 搜索系统中一个长期的问题是结果多样性。从产品角度讲&#xff0c;给用户多种多样的选择&#xff0c;有助于提升用户体验及业务指标。 多样性需求和模型的目标是相矛盾的&#xff0c;因为传统ctr模型是 point wise&#xff0c;只看单个相关性不管相邻之间item差异。 …

设计模式-笔记

文章目录七大原则单例模式桥模式 bridge观察者模式 observer责任链模式 Chain of Responsibility命令模式 Command迭代器模式 Iterator中介者模式 Mediator享元模式 Flyweight Pattern组合模式 composite装饰模式 Decorator外观模式 Facade简单工厂模式工厂方法模式工厂抽象模式…

数学小课堂:无穷小(平均速度和瞬间速度的关系)

文章目录 引言I 速度1.1 平均速度1.2 瞬间速度(某一时刻特定的速度)1.3 解释飞箭是静止的悖论II 导数2.1 概念2.2 导数的现实影响2.3 微积分的意义III 无穷小3.1 贝克莱挑战牛顿(无穷小悖论)3.2 无穷小的定义引言 柯西和魏尔斯特拉斯给出的无穷小的定义: 它不是零;它的绝对…

【GUI】Robo 3T(Studio 3T Free) for Mongodb安装与使用教程

下载 robo 3T现已更名为studio 3T free&#xff0c;官网即可下载 studio 3T free下载地址 安装 mac电脑下载的是dmg安装包&#xff0c;直接正常安装即可&#xff0c;windows电脑也是一样的&#xff0c;不需要配置环境&#xff0c;安装即可使用。&#xff08;前提是你已经安装…

什么是接口测试,我们如何实现接口测试?

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

SkyWalking简介和安装

APM系统 早期的监控系统功能比较单一&#xff0c;主要以监控CPU、内存、网络、I/O等基础设置为主&#xff08;cacti、nagios&#xff09; 后来随着中间件技术的不断发展&#xff0c;监控系统也开始监控缓存、数据库、MQ等各种基础组件的性能&#xff08;zabbix、prommethus&a…

【MinIO】文件断点续传和分块合并

【MinIO】文件断点续传和分块合并 文章目录【MinIO】文件断点续传和分块合并0. 准备工作1. 检查文件是否存在1.1 定义接口1.2 编写实现方法2. 检查分块文件是否存在2.1 定义接口2.2 编写实现方法3. 上传分块文件接口3.1 定义接口3.2 编写实现方法4. 合并分块文件接口4.1 定义接…

Python - Opencv应用实例之CT图像检测边缘和内部缺陷

Python - Opencv应用实例之CT图像检测边缘和内部缺陷 将传统图像处理处理算法应用于CT图像的边缘检测和缺陷检测,想要实现效果如下: 关于图像处理算法,主要涉及的有:灰度、阈值化、边缘或角点等特征提取、灰度相似度变换,主要偏向于一些2D的几何变换、涉及图像矩阵的一些统…

java中使用protobuf总结

基本没怎么接触过java编程&#xff0c;别的团队发过来一个用java编写的存储pb的文件&#xff0c;让拆分和解析&#xff0c;硬着头皮做一下&#xff0c;在此将步骤做个记录&#xff1a;下载安装protobufhttps://github.com/protocolbuffers/protobuf/tags?afterv3.6.1.2编译pro…