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

这篇具有很好参考价值的文章主要介绍了SQL使用技巧(6)HIVE开窗函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

一.构建数据

如果没有现成可用HIVE库,可以参见本人 大数据单机学习环境搭建 系列文章。
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/

SQL使用技巧(6)HIVE开窗函数
1.4验证数据

select * from func_wins;

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

二.排序开窗

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;

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

三.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;

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

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;

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

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
;

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

四.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;

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

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;

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

五.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;

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

六.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;

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

七.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;

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

八.ntile开窗

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

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

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

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

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


声明:本文所载信息不保证准确性和完整性。文中所述内容和意见仅供参考,不构成实际商业建议,可收藏可转发但请勿转载,如有雷同纯属巧合文章来源地址https://www.toymoban.com/news/detail-474436.html

到了这里,关于SQL使用技巧(6)HIVE开窗函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于Hive的使用技巧

    前言 Hive是一个基于Hadoop的数据仓库基础架构,它提供了一种类SQL的查询语言,称为HiveQL,用于分析和处理大规模的结构化数据。 Hive的主要特点包括: 可扩展性:Hive可以处理大规模的数据,支持高性能的并行化执行。 数据抽象:Hive将数据抽象为表,可以通过HiveQL进行查询

    2024年02月14日
    浏览(27)
  • 【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表

    【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串UNION与OR的使用注意事项 【SQL开发实战技巧】系列

    2023年04月09日
    浏览(38)
  • SQL 的window开窗函数简单使用

    开窗函数不论是spark的还是clickhouse的在日常的查询中是一个很常用的功能,特别是他想要解决的问题和group by的很类似,这两种容易引起混淆,本文就简单的描述下开窗函数的简单用法 首先窗口函数和group by是完全没有交集的,他们完全没有任何关系,group by聚合数据后会导致

    2024年02月09日
    浏览(32)
  • MySQL特殊函数使用技巧

    使用group_concat函数,可以轻松的把分组后,name 相同的数据拼接到一起,组成一个字符串,用逗号分隔。 通过该函数就能获取字符长度。 在某个字符串中的位置 将字符串中的字符 A 替换成 B。REPLACE(name,‘A’,‘B’) 获取当前时间 这样就能将 order 表中的部分数据,非常轻松插

    2024年02月04日
    浏览(27)
  • MATLAB Cell函数使用技巧

    MATLAB Cell 函数使用技巧 谈谈MATLAB中cell函数 如果p为一个数,那么h(1)=p,是没有问题的。 如果p为一个向量,那么h(1,:)=p是没有问题的。 如果p是一个矩阵的话,上面的两种赋值方法都是会有错误的。 那么要如何处理呢? 这时就用到了cell数据类型了。cell的每个单元都可以存储任

    2024年02月08日
    浏览(36)
  • 使用指针或引用作为函数参数的编程技巧

    空指针检查: 使用指针允许在函数内部检查传递的指针是否为 nullptr 。这使得在函数内部能够处理空指针的情况,增加代码的健壮性。如果使用引用,无法表示空值,而使用指针则可以通过传递 nullptr 来表示缺失的数据。

    2024年02月16日
    浏览(35)
  • 【大数据之Hive】十六、Hive-HQL函数之窗口函数(开窗函数)

      先定义了窗口的大小(按行来算),然后对窗口内的行的数据进行计算,再将计算结果返回给改行。   窗口函数包括窗口和函数两部分,窗口用于定义计算范围,函数用于定义计算逻辑,窗口函数只会在原来的表上增加一列结果列,不改变原来的数据。 函数:   绝

    2024年02月11日
    浏览(32)
  • C#析构函数解析:资源管理的精要和使用技巧

      在C#中,析构函数(Destructor)是一个特殊的方法,用于清理对象占用的资源。它是由垃圾回收器在对象被销毁时自动调用的。析构函数的原理是在对象即将被回收时执行一些清理操作,例如释放非托管资源或执行一些对象销毁前的必要操作。 调用时机:  当对象被垃圾回收

    2024年01月24日
    浏览(41)
  • Excel小技巧,使用函数(INDEX+MATCH)快速进行条件查询

    目录 Excel小技巧,使用函数(INDEX+MATCH)快速进行条件查询 1、例如:快速查找下图右边同学的总分  2、在条件查询区域,总分单元格中输入函数【=INDEX(E:E,MATCH(H2,A:A,0))】即可  3、INDEX(E:E  函数为查找结果所在列,MATCH(H2,A:A,0)函数中H2为查找值,A:A为查找所在列,0为精确匹配

    2024年02月10日
    浏览(48)
  • C++回调函数精解:基础使用和高级技巧一网打尽

      概述: C++回调函数提供了灵活的编程方式。基础使用演示了如何定义和调用简单的回调,而高级使用则展示了返回值非 `void` 的回调和Lambda表达式的灵活性。这种机制使程序更模块化、可维护。 在C++中,回调函数可以用于实现基础和高级的功能。以下是一个包含基础和高级

    2024年03月18日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包