SQL使用技巧(6)HIVE开窗函数

news2024/9/23 1:25:57

专题:SQL使用技巧——实践是检验SQL函数的唯一标准

  • 一.构建数据
  • 二.排序开窗
  • 三.sum开窗(重点内容)
    • 3.1累加与求和
    • 3.2窗口表达式
    • 3.3场景模拟
  • 四.count开窗
    • 4.1计数规则
    • 4.2计数与排序
  • 五.max和min开窗
  • 六.lead和lag开窗
  • 七.first_value和last_value开窗
  • 八.ntile开窗

开窗函数的使用铁律:不要滥用 先想明白自己要实现什么样的功能,然后再去实践。没有目的的尝试段不可取,会难以理解各开窗函数的真正用法。

一.构建数据

1.1Hive建表

-- 建表
drop table func_wins;
create table func_wins(
`id` bigint, 
  `name` string, 
  `trad_amt` int comment '营业金额', 
  `province` string, 
  `city` string)
row format serde 
  'org.apache.hadoop.hive.serde2.lazy.lazysimpleserde' 
with serdeproperties ( 
  'field.delim'=',', 
  'serialization.format'=',') 
stored as inputformat 
  'org.apache.hadoop.mapred.textinputformat' 
outputformat 
  'org.apache.hadoop.hive.ql.io.hiveignorekeytextoutputformat'
location
  'hdfs://192.168.31.128:9000/user/hive/warehouse/func_wins'
;

1.2数据准备

1,张三,30,广东省,中山市
2,李四,30,广东省,佛山市
3,和尚,10,广东省,东莞市
4,政委,60,广东省,东莞市
5,李委,40,浙江省,金华市
6,王委,80,浙江省,台州市
7,张委,100,浙江省,宁波市
8,赵委,100,浙江省,衢州市
9,白委,50,浙江省,绍兴市

1.3保存为HDFS文件

# put数据入库
hadoop fs -put /home/func_wins.txt /user/hive/warehouse/func_wins/

在这里插入图片描述
1.4验证数据

select * from func_wins;

在这里插入图片描述

二.排序开窗

2.1函数特性
row_number() over() 不存在重复的排名,即使 order by 的值完全一样也分大小,在取数必须唯一时特别适用;
rank() over() 存在重复的排名,排名会占位置,符合日常生活中的排序方式,并列之后会出现空挡;
dense_rank() over() 存在重复排名,且排名不占位置,所有的排序序号是连续的。

排序函数的基本规则:能靠前的肯定不会让靠后,5个人排名可能只有前4名,没有第5名,能并列第4绝对不会并列成第5。当排序函数与其它函数结果相似时,这一点非常重要,能否等价互换一定要慎重。具体差异见4.2章节内容。

2.2示例检验

-- row_number()无重复排序, rank()占位排序, dense_rank()不占位排序
select *
  ,row_number() over(partition by province order by trad_amt desc) rn
  ,rank() over(partition by province order by trad_amt desc) rk
  ,dense_rank() over(partition by province order by trad_amt desc) dr
from func_wins;

在这里插入图片描述

三.sum开窗(重点内容)

3.1累加与求和

-- sum()开窗加了order by 是累加不是求和
select *
  -- 求和,分组内所有行
  ,sum(trad_amt) over(partition by province) sm_amt
  -- 求和,分组内所有行
  ,sum(trad_amt) over(partition by province,city) sm_amt2
  -- 累加,分组内逐个累加
  ,sum(trad_amt) over(partition by province order by id) addup_amt
  -- 累加,无分组,不断累加直至结束
  ,sum(trad_amt) over(order by id) addup_amt2
from func_wins;

在这里插入图片描述

3.2窗口表达式

窗口表达式提供了控制行范围的能力,计算变的非常灵活,具体示例如下

关键字是 rows between, 选项如下
preceding 往前
following 往后
current row 当前行
unbounded 边界
unbounded preceding 表示从前面的起点
unbounded following 表示到后面的终点
select *
  -- 1 累加
  ,sum(trad_amt) over(partition by province order by id) amt1
  -- 2 求和, 分组内所有行
  ,sum(trad_amt) over(partition by province) amt2
  -- 3 同2, 从头到尾,分组内所有行
  ,sum(trad_amt) over(partition by province order by id rows between unbounded preceding and unbounded following) amt3
  -- 4 向前3行至当前行
  ,sum(trad_amt) over(partition by province order by id rows between 3 preceding and current row) amt4
  -- 5 向前2行 向后1行
  ,sum(trad_amt) over(partition by province order by id rows between 2 preceding and 1 following) amt5
  -- 6 当前行至最后一行
  ,sum(trad_amt) over(partition by province order by id rows between current row and unbounded following) amt6
from func_wins;

在这里插入图片描述

3.3场景模拟

示例 bal1:营业收入场景,已知两省份最终销售额都是1000,计算每笔 收入 后的累计销售金额,其中id代表业务产生的先后顺序;
示例 bal2:账户消费场景,已知两省份最终余额都是1000,计算每笔 开支 后账户余额,其中id代表消费产生的先后顺序;
示例 bal3:销售目标场景,两省份的销售目标都是1000,计算每一笔 交易 后距离目标还差多少,其中id代表业务产生的先后顺序;

select t.*,(1000-sm_amt+addup_amt) bal1,(1000+sm_amt-addup_amt) bal2,(1000-addup_amt) as bal3
from
(select *
  ,sum(trad_amt) over(partition by province) sm_amt
  ,sum(trad_amt) over(partition by province order by id rows between unbounded preceding and unbounded following) sm_amt2
  ,sum(trad_amt) over(partition by province order by id) addup_amt
from func_wins) t
;

在这里插入图片描述

四.count开窗

4.1计数规则

聚合函数的另一个常用开窗是count开窗——分组计数。当count() over()带有 order by 的时候,分组计的都是到当前order by值的数量,不同于排序函数,但可在特殊情况下使用此特性
下方示例中,cnt1、cnt3、cnt4是较为常见的用法,其中cnt3、cnt4相结合的方式有被用于拉链表的案例。

-- count()开窗加了order by 相当于是rank()排序开窗函数了
select *
  ,count(1) over(partition by province) cnt1
  ,count(1) over(partition by province order by trad_amt) cnt2
  ,count(1) over(partition by province order by trad_amt rows BETWEEN UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING) cnt2a
  ,count(1) over(partition by province,trad_amt) cnt3
  ,count(1) over(partition by province,trad_amt order by id) cnt4
from func_wins;

在这里插入图片描述

4.2计数与排序

开窗计数结果不等同于开窗排序结果,要留心区分两者差异,避免错误使用。
使用场景:各组排名前2的人员获奖,但每组获奖人员必须在2人以内,且要绝对公平,即并列排名第2的不能获奖,此时便可以使用count() over()满足要求。具体见下方数据差异。

select *
  ,count(1) over(partition by province order by trad_amt) cnt1
  ,rank() over(partition by province order by trad_amt) rk1
  ,dense_rank() over(partition by province order by trad_amt) dk1
  ,count(1) over(order by trad_amt) cnt2
  ,rank() over(order by trad_amt) rk2
  ,dense_rank() over(order by trad_amt) dk2
from func_wins;

在这里插入图片描述

五.max和min开窗

开窗获取分组内最大值最小值,用来计算差距、数据标准化都是有用的

-- max()开窗 min()开窗
select *
  ,max(trad_amt) over(partition by province) max_amt
  ,max(trad_amt) over(partition by province,city) max_amt_asse
  ,min(trad_amt) over(partition by province) min_amt
  ,min(trad_amt) over(partition by province,city) min_amt_asse
from func_wins;

在这里插入图片描述

六.lead和lag开窗

数据的上下漂移,计算同环比时非常实用
lag(col,N,default) 作用于col字段,向上取N行,如果向上为空给个默认值,没有默认值就是null
lead(col,N,default) 作用于col字段,向下取N行,如果向下为空给个默认值,没有默认值就是null

-- lead 和 lag, 数据的上线漂移
select *
  ,lag(trad_amt) over(partition by province order by id) lag_amt
  ,lead(trad_amt) over(partition by province order by id) lead_amt
  ,lead(trad_amt,1,0) over(partition by province order by id) lead_1_amt
  ,lead(trad_amt,2,0) over(partition by province order by id) lead_2_amt
from func_wins;

在这里插入图片描述

七.first_value和last_value开窗

last_value()默认从第一条到当条,与sum和count开窗相似,同样也可以通过窗口表达式灵活使用(3.2章节)。

-- last_value()默认从第一条到当条
select *
  ,first_value(trad_amt) over(partition by province order by id) first_amt
  ,first_value(trad_amt) over(partition by province order by id desc) first_amt2
  ,last_value(trad_amt) over(partition by province) last_amt
  ,last_value(trad_amt) over(partition by province order by id) last_amt2
  ,last_value(trad_amt) over(partition by province order by id rows between unbounded preceding and unbounded following) last_amt3
from func_wins;

在这里插入图片描述

八.ntile开窗

ntile 将每个分组内的数据分为指定的若干个桶里,并且为每一个桶分配一个桶编号。分配时会尽量平均分配,如果不能平均分配,优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。

-- ntile 分桶函数
select *
  ,ntile(3) over(partition by province order by id) ntile_code
from func_wins;

在这里插入图片描述

最终提示:开窗函数虽好用,但不可滥用

纸上得来终觉浅,绝知此事要躬行。SQL之路只有一个标准答案——实践成真。


声明:本文所载信息不保证准确性和完整性。文中所述内容和意见仅供参考,不构成实际商业建议,可收藏可转发但请勿转载,如有雷同纯属巧合

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

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

相关文章

RabbitMq创建交换机和队列

1. 网页登录 IP:1572 2. 输入登录账号密码 admin admin 3. 点击Exchanges 添加交换机Platform_AlarmEngineInterface 和Rg_Platform_AlarmEngineInterface ,Type选择topic 4. 添加队列 VIDEO_Alarm_platform、watch_ftp、RG_VIDEO_Alarm_platform、RG_VIDEO_…

远程进入服务器界面黑屏如何处理?

​  远程登录服务器出现黑屏是很常见的问题,可能是由于多种原因引起的。但不管是哪种原因,当远程连接成功,进入桌面显示黑屏都会让用户感到困扰,无法正常使用服务器。下面我们将为您介绍一些常见的解决方法。 1. 重启远程桌面服…

js深拷贝和浅拷贝

👉十分钟学会 前端面试题 js 深拷贝与浅拷贝_前端深拷贝和浅拷贝面试题_Mar-30的博客-CSDN博客 目录 背景: 概念:核心是创建新地址 方法: 浅拷贝: Object.assign() 方法:Object.assign(拷贝的对象&am…

k8s证书过期

[rootmaster1 ~]# kubectl get nodes Unable to connect to the server: x509: certificate has expired or is not yet valid: current time 1.master服务器: # 备份 kubernetes配置 cp -r /etc/kubernetes /etc/kubernetes_bak # 检测证书过期 kubeadm certs…

数智荣耀丨美格智能荣登2023年度中国数智转型标杆企业榜

5月31日,2023数智产业领袖峰会在北京召开,本届大会由智次方—物联网智库主办,大会以大模型时代的“破”与“立”为主题,汇聚产业领袖、专家学者、投资机构、创新企业等各界精英,共同探讨企业如何利用新技术实现“破圈”…

【地平线X3M平台点亮sensor出现问题的分析】

转自地平线论坛经验 1. IC通讯失败的问题以及排查方法。 外界的图像数据一般是通过sensor感知,然后通过mipi接口进入到地平线X3M这款AI芯片的视频处理模块,模块对视频图像做比如放大、缩小、旋转等处理。 问题:IC通讯失败,错误…

手机MT4平台怎么样?手机版MT4平台使用教程教学

外汇是一个全球化的去中心化交易市场,与股票这样只提供一种报价的集中交易不同,在外汇市场中,货币的报价都不是单一的,意味着不同的外汇交易平台的报价会有所不同。以前外汇交易散户是很难进入市场的,参与者主要是银行…

功能强大UI美观的视频答题猜歌闯关娱乐微信小程序源码

正文: 功能强大UI美观的视频答题猜歌闯关娱乐微信小程序源码下载 后台管理资源本地化带数据和视频教程,这是一款拥有后端的闯关娱乐小程序。支持个人小程序和企业小程序上线运营功能强大齐全,带数据本地化(数据在自己服务器自己管理无需担心第三方失效…

【TCP 协议3】提高效率的五大机制

文章目录 前言一、滑动窗口与高速重传1, 什么是滑动窗口2, 什么是高速重传2.1, ack 丢包2.2, 数据丢包 二、流量控制1, 什么是流量控制 三、拥塞控制1, 什么是拥塞控制 四、延迟应答1, 什么是延迟应答 五、捎带应答1, 什么是捎带应答 总结 前言 各位读者好, 我是小陈, 这是我的…

Ansible基础3——playbook

文章目录 一、基本了解二、编写playbook2.1 单剧本2.2 多剧本2.3 特权升级2.4 语法优化 三、模块查找 一、基本了解 为什么要写playbook? 前面我们可以使用临时命令对受控机进行操作,但当有重复性的工作时就不能这么玩了,因为你要一遍遍的去执…

攻防世界-easy_RSA

题目如下:在一次RSA密钥对生成中,假设p473398607161,q4511491,e17 求解出d 1. RSA算法介绍 RSA算法是一种非对称加密算法,由三位计算机科学家Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出并命名。 它采用一…

Vue 基础组件二次封装的高级技巧及方法,能更优雅的进行二次封装组件(props 属性和 event 事件的透传、子组件插槽暴露、第三方组件方法继承)

前言 本人持续开源了Vue2基于ElementUi&AntdUi再次封装的Tui基础组件和Vue3基于Element-plus再次封装的TuiPlus基础组件,在组件封装的过程中提取了 props 属性和 event 事件的透传、子组件插槽暴露等,借此总结一下!!大佬略过!…

把VS Code打造成后端开发的宇宙IDE,也挺爽

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注! 作者:维生素P|慕课网优质作者 工欲善其事必先利其器,提高程序员的开发效率必须要有一个好的开发工具。而一旦提到开发工具&#xff…

深度解析Linux读写锁逻辑

一、Linux为何会引入读写锁? 除了mutex,在linux内核中,还有一个经常用到的睡眠锁就是rw semaphore(后文简称为rwsem),它到底和mutex有什么不同呢?为何会有rw semaphore?无他&#x…

[Mysql_DB]自动写入系统时间——注意低版本数据库操作

创建商品表包含字段create_time和update_time,并设置默认值为当前时间 实例 使用 CREATE TABLE 语句来创建一个商品表,并为其添加 create_time 和 update_time 字段,同时将这两个字段的默认值设置为当前时间。以下是一个示例: CREATE TABLE …

最新版本 Stable Diffusion 开源 AI 绘画工具之文本转换(Embedding)以及脚本(Script)高级使用篇

✨ 目录 🎈 文本转换 / Textual Inversion🎈 自定义Embedding / Textual Inversion🎈 脚本 / Script🎈 脚本 / Prompt matrix🎈 脚本 / X/Y/Z plot 🎈 文本转换 / Textual Inversion 这个功能其实就是将你…

SuperMap Hi-Fi 3D SDK for Unity制作游戏引擎材质

kele 一、使用背景 在交通,电力,规划等行业中,有的对象常常具有很强的质感,比如金属质感的 钢轨,电力塔;陶瓷材质的绝缘子;玻璃材质的建筑幕墙等,但常规方式的表现效果 往往差强人意…

AUTOSAR APP临摹1~Quick Start 模块

已实现逻辑 demo5 页面跳转 mainwindow.ui相当于simulink界面点击Quick Start进入welcome.ui界面在welcome.ui中大概包含7个页面页面之间通过next、back按钮翻页第0页没有back、最后一页点击next退出welcome.ui,回到mainwindow.ui 条件显示 C/C选项页面中&#xff…

7 步提升私有化部署的极狐GitLab 实例安全等级

目录 指导准则 分层安全,纵深防御 保密 ≠ 安全 减少攻击面 7 步保障私有化部署实例安全 第一步:开启多因素认证 第二步:加强额外的注册检查 第三步:限制群组和项目可见性 第四步:强化 SSH 设置 第五步&…

labelimg闪退解决方法(之前使用过labelimg,但新一次使用,打开文件夹无反应,再次打开闪退的问题)

问题描述: 之前使用过labelimg进行好多次的标注,但新一次运行使用,发现打开目录无反应,再次打开闪退的问题,重启电脑并且从新运行labelimg仍然无效。 解决方法: 关闭labelimg,然后删除文件C…