HIVE --- 窗口函数

news2025/7/29 10:35:34

目录

简介

概念

数据准备

聚合函数+over

partition by子句

order by子句

window子句

窗口函数中的序列函数

ntile

rank、dense_rank、row_number

LAG、LEAD

first_value、last_value


简介

本文主要介绍hive中的窗口函数.hive中的窗口函数和sql中的窗口函数相类似,都是用来做一些数据分析类的工作,一般用于olap分析(在线分析处理)。

概念

我们都知道在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的.但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数.

在深入研究Over字句之前,一定要注意:在SQL处理中,窗口函数都是最后一步执行,而且仅位于Order by字句之前。

数据准备

我们准备一张orders表,字段分别为name,orderdate,cost.数据内容如下:

jack,2015-01-01,10
tony,2015-01-02,15
jack,2015-02-03,23
tony,2015-01-04,29
jack,2015-01-05,46
jack,2015-04-06,42
tony,2015-01-07,50
jack,2015-01-08,55
mart,2015-04-08,62
mart,2015-04-09,68
neil,2015-05-10,12
mart,2015-04-11,75
neil,2015-06-12,80
mart,2015-04-13,94

聚合函数+over

常见聚合函数(count(),sum(),max(),min(),avg()……)

查询在2015年4月份购买过的顾客及总人数,我们便可以使用窗口函数去去实现

select name,count(*) over ()
from orders
where substring(orderdate,1,7) = '2015-04'

 在2015年4月一共有5次购买记录,mart购买了4次,jack购买了1次.事实上,大多数情况下,我们是只看去重后的结果的.针对于这种情况,我们有两种实现方式

第一种:

select distinct name, count(*) over ()
from orders
where substring(orderdate, 1, 7) = '2015-04';

第二种:

select name, count(*) over ()
from orders
where substring(orderdate, 1, 7) = '2015-04'
group by name;

partition by子句

Over子句之后第一个提到的就是Partition By.Partition By子句也可以称为查询分区子句,非常类似于Group By,都是将数据按照边界值分组,而Over之前的函数在每一个分组之内进行,如果超出了分组,则函数会重新计算.

顾客的购买明细及月购买总额,可以执行如下的sql

select name,orderdate,cost,sum(cost) over(partition by month(orderdate))
from orders

order by子句

上述的场景,假如我们想要将cost按照月进行累加.这时我们引入order by子句.

order by子句会让输入的数据强制排序(文章前面提到过,窗口函数是SQL语句最后执行的函数,因此可以把SQL结果集想象成输入数据)。Order By子句对于诸如Row_Number(),Lead(),LAG()等函数是必须的,因为如果数据无序,这些函数的结果就没有任何意义。因此如果有了Order By子句,则Count(),Min()等计算出来的结果就没有任何意义。

顾客的购买明细及月购买总额以及过程

select name, orderdate, cost, sum(cost) over (partition by name
 order by orderdate) sum from orders;

window子句

我们在上面已经通过使用partition by子句将数据进行了分组的处理.如果我们想要更细粒度的划分,我们就要引入window子句了.

我们首先要理解两个概念: 
- 如果只使用partition by子句,未指定order by的话,我们的聚合是分组内的聚合. 
- 使用了order by子句,未使用window子句的情况下,默认从起点到当前行.

当同一个select查询中存在多个窗口函数时,他们相互之间是没有影响的.每个窗口函数应用自己的规则.

window子句: 

- preceding:往前 

- following:往后 

- current row:当前行 

- unbounded:起点

- unbounded preceding:表示从前面的起点

- unbounded following:表示到后面的终点

按照name进行分区,按照购物时间进行排序,做cost的累加.

select name,
       orderdate,
       cost,
       -- 全表数据的cost总和
       sum(cost) over ()                                             as row1,
       --个人消费总和
       sum(cost) over (partition by name)                            as row2,
       sum(cost) over (partition by name
           rows between unbounded preceding and unbounded following) as row22,
       --截止到当前日期个人消费总和
       sum(cost) over (partition by name order by orderdate)         as row3,
       --同row3
       sum(cost) over (partition by name order by orderdate
           rows between unbounded preceding and current row)         as row4,
       --当前消费额与上一次消费额的总和
       sum(cost) over (partition by name order by orderdate
           rows between 1 preceding and current row )                as row5,
       --当前消费与上一次消费以及后一次的消费总额
       sum(cost) over (partition by name order by orderdate
           rows between 1 preceding and 1 following )                as row6,
       --当前消费额与后面所有消费的总额
       sum(cost) over (partition by name order by orderdate
           rows between current row and unbounded following)         as row7,
       --当前日期以及后面三次的消费总额
       sum(cost) over (partition by name order by orderdate
           rows between current row and 3 following)                 as row8
from orders;

窗口函数中的序列函数

主要序列函数是不支持window子句的.

hive中常用的序列函数有下面几个:

ntile

  • ntile(n),用于将分组数据按照顺序切分成n片,返回当前切片值

  • ntile不支持rows between,比如 ntile(2) OVER(partition by name order by orderdate rows between 3 preceding  and current row)

  • 如果切片不均匀,默认增加第一个切片的分布
select name,
       orderdate,
       cost,
       -- 全局数据切片
       ntile(5) over ()                                      as row1,
       -- 按照name进行分组,在分组内将数据切成3份
       ntile(3) over (partition by name)                     as row2,
       -- 全局按照name升序排列,数据切成3份
       ntile(3) over (order by name )                        as row3,
       -- 按照name分组,在分组内按照cost升序排列,数据切成3份
       ntile(3) over (partition by name order by cost desc ) as row4
from orders;

        

rank、dense_rank、row_number

函数名描述
RANK()分区中当前行的排名,带有间隙
DENSE_RANK()分区中当前行的排名,无间隙
ROW_NUMBER()其分区中的当前行数

row_number()从1开始,按照顺序,生成分组内记录的序列,row_number()的值不会存在重复,当排序的值相同时,按照表中记录的顺序进行排列 
rank() 生成数据项在分组中的排名,排名相等会在名次中留下空位 
dense_rank() 生成数据项在分组中的排名,排名相等会在名次中不会留下空位

**注意: 
rank和dense_rank的区别在于排名相等时会不会留下空位.**

为了更直观的看出他们区别,在加一行数据

insert into orders
values ('jack', '2015-02-04', 42);
select name,
       orderdate,
       cost,
       row_number() over (partition by name order by cost desc ) as row1,
       rank() over (partition by name order by cost desc )       as row2,
       dense_rank() over (partition by name order by cost desc ) as row3
from orders;

LAG、LEAD

函数名描述
LAG()分区内滞后当前行的参数值
LEAD()分区内当前行前导行的参数值
select name,
       cost,
       lag(orderdate, 1, '1900-01-01') over (partition by name order by orderdate) as row1,
       orderdate,
       lead(orderdate) over (partition by name order by orderdate)                 as row2
from orders;

first_value、last_value

first_value取分组内排序后,截止到当前行,第一个值 
last_value取分组内排序后,截止到当前行,最后一个值

select name,
       orderdate,
       cost,
       first_value(orderdate) over (partition by name order by orderdate) as row1,
       last_value(orderdate) over (partition by name order by orderdate)  as row2
from orders;

关于Parttion by:

  Parttion by关键字是Oracle中分析性函数的一部分,用于给结果集进行分区。它和聚合函数Group by不同的地方在于它只是将原始数据进行名次排列,能够返回一个分组中的多条记录(记录数不变),而Group by是对原始数据进行聚合统计,一般只有一条反映统计值的结果(每组返回一条)。

TIPS

  • 使用rank over()的时候,空值是最大的,如果排序字段为null, 可能造成null字段排在最前面,影响排序结果。
  • 可以这样: rank over(partition by course order by score desc nulls last)

总结:

  在使用排名函数的时候需要注意以下三点:

  1、排名函数必须有 OVER 子句。

  2、排名函数必须有包含 ORDER BY 的 OVER 子句。

  3、分组内从1开始排序。

 

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

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

相关文章

批量操作文件功能-课后程序(JAVA基础案例教程-黑马程序员编著-第七章-课后作业)

【实验7-1】 批量操作文件功能 任务介绍 1.任务描述 在日常工作中,经常会遇到批量操作系统文件的事情,通常情况下,只能手动重复的完成批量文件的操作,这样很是费时费力。本案例要求编写一个文件管理器,…

(二十六)、项目打包H5+微信小程序+app【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1,打包H5发布上线到前端页面托管 1.1 上传所有DBschema和云函数 上传所有DBschema到云服务空间 上传所有云函数到云服务空间 1.2 Hbuilderx基础配置 点击manifest.json文件----web配置: 点击发行—H5 1.3 H5打包完成 使用vscode中的live serve…

【C语言进阶】动态内存管理详解与常见动态内存错误以及柔性数组使用与介绍

​ ​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:C语言进阶 🎯长路漫漫浩浩,万事皆有期待 文章目录1.动态内存1.1 概述…

运营级手机直播平台源码 短视频直播带货APP源码

短视频直播带货APP源码 全开源原生直播APP源码 前端:原生APP 安卓端:Java 苹果端:OC 后台:PHP 数据库:Mysql 技术框架:Thinkphp5.1 系统特色功能包括:礼物系统;提现方式&#…

2月 公司来一00后卷王,我们这帮老油条真干不过.....

都说00后躺平了,但是有一说一,该卷的还是卷。这不,我们公司来了个00后,工作没两年,跳槽到我们公司起薪18K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 2023年春…

【算法】——并查集

作者:指针不指南吗 专栏:算法篇 🐾或许会很慢,但是不可以停下🐾 文章目录1.思想2.模板3.应用3.1 合并集合3.2 连通块中点的数量1.思想 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题…

ESP32 Arduino EspNow点对点双向通讯

ESP32 Arduino EspNow点对点双向通讯✨本案例分别采用esp32和esp32C3之间点对点单播无线通讯方式。 🌿esp32开发板 🌾esp32c3开发板 🔧所需库(需要自行导入到Arduino IDE library文件夹中,无法在IDE 管理库界面搜索下载到该库)&am…

【GO】k8s 管理系统项目[前端部分16–前端布局]

【GO】k8s 管理系统项目[前端部分–前端布局] 1. 前端布局 2. Layout 2.1 layout src/layout/Layout.vue <template><div class"common-layout"><el-container><el-side width"200">Aside</el-side><el-container>…

哪些骨传导运动蓝牙耳机好,分享几款不错的骨传导耳机

​骨传导耳机在运动中有很多优势&#xff0c;它是一款不入耳的耳机&#xff0c;适合在跑步、骑行、爬山等运动中使用&#xff0c;如果你是一个爱运动的人&#xff0c;骨传导耳机是不错的选择。由于骨传导技术不需要塞入耳朵中就能听到音乐&#xff0c;所以不会产生任何不适感。…

计算机图形学期末复习笔记

计算机图形学 ch1绪论 1.1计算机图形学及其概念 计算机图形学&#xff08;Computer Graphics&#xff09;是研究怎样利用计算机来生成、处理和显示图形的原理、方法和技术的学科。 cg研究对象是图形 图形的要素 几何&#xff08;轮廓、点、线、面&#xff09;非几何要素&…

前向传播与反向传播参数的更新方式(略高于高中数学水平)(附公式、代码)

前向传播与反向传播意义及其参数的更新方式 文章目录前向传播与反向传播意义及其参数的更新方式一、前言二、前反向传播的作用三、前向传播四、反向传播代码一、前言 因为本身非科班出身&#xff0c;数学又学的很差&#xff0c;一直都是傻瓜式地用tensorflow和pytorch搭网络。…

【容器】学习docker容器网络

在前面讲解容器基础时&#xff0c;曾经提到过一个 Linux 容器能看见的“网络栈”&#xff0c;实际上是被隔离在它自己的 Network Namespace 当中的。 而所谓“网络栈”&#xff0c;就包括了&#xff1a;网卡&#xff08;Network Interface&#xff09;、回环设备&#xff08;L…

Mac mini 外接移动硬盘无法写入或者无法显示的解决方法

文章目录1. 背景2. 让NTFS格式的移动硬盘正常读写方法3. 打开“启动安全性实用工具”4. 更改“安全启动”设置1. 背景 刚买mac min&#xff08;2023年2月3日&#xff09;不久&#xff0c;发现macOS的玩起来并不容易&#xff0c;勇习惯了windows系统的习惯&#xff0c;感觉 mac…

【storybook】你需要一款能在独立环境下开发组件并生成可视化控件文档的框架吗?(二)

storybook回顾继续说说用法配置文件介绍回顾 上篇博客地址&#xff1a; https://blog.csdn.net/tuzi007a/article/details/129192502说了部分用法。 继续说说用法 配置文件介绍 开发环境的配置都在.storybook目录中&#xff0c;里面包含了2个文件 main.js preview.js先看m…

STM32 触摸屏移植GUI控制控件

目录 1、emWin 支持指针输入设备。 2、 模拟触摸屏驱动 3、实现触摸屏的流程 3.1 实现硬件函数 3.2 实现对GUI_TOUCH_Exec()的定期调用 3.3 使用上一步确定的值&#xff0c;在初始化函数LCD_X_Config&#xff08;&#xff09;当中添加对GUI_TOUCH_Calibrate()的调用 4、…

Kubernetes入门教程 --- 使用二进制安装

Kubernetes入门教程 --- 使用二进制安装1. Introduction1.1 架构图1.2 关键字介绍1.3 简述2. 使用Kubeadm Install2.1 申请三个虚拟环境2.2 准备安装环境2.3 配置yum源2.4 安装Docker2.4.1 配置docker加速器并修改成k8s驱动2.5 时间同步2.6 安装组件3. 基础知识3.1 Pod3.2 控制…

【一些回忆】2022.02.26-2023.02.26 一个普通男孩蜕变的365天

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f91e; 作者&#xff1a;那就叫我亮亮叭 &#x1f4d5; 专栏&#xff1a;一些回忆 为什么选择在这个时间节点回忆一下呢&#xff1f; 一是因为今天距离2023高考仅剩1…

双指针法应用总结

一、双指针法&#xff08;一&#xff09;概况1.类型&#xff1a;快慢指针&#xff08;相同方向循环&#xff09;、对撞指针&#xff08;相反方向循环&#xff09;、滑动窗口2.用途&#xff1a;提高效率&#xff0c;通常能将将O(n^2)的时间复杂度&#xff0c;降为O(n)3.可应用的…

selenium基本操作

爬虫与反爬虫之间的斗争爬虫&#xff1a;对某个网站数据或图片感兴趣&#xff0c;开始抓取网站信息&#xff1b;网站&#xff1a;请求次数频繁&#xff0c;并且访问ip固定&#xff0c;user_agent也是python&#xff0c;开始限制访问&#xff1b;爬虫&#xff1a;通过设置user_a…

数据库浅谈之 DuckDB AGG 底层实现

数据库浅谈之 DuckDB AGG 底层实现 HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是数据库浅谈系列&#xff0c;收录在专栏 DATABASE 中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列阿呆将记录一些数据库领域相关的知…