IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Hive:窗口函数 -> 正文阅读

[大数据]Hive:窗口函数

一、窗口函数是什么

二、窗口函数分类

一、累计计算窗口函数

1、sum() over()

在工作中经常遇到计算截止某月的累计数值,此时需要用sum()开窗
比如给一张交易表user_trade:
在这里插入图片描述
现在需要计算出2018年每月的支付总额和当年累计支付总额:

select 
        a.month,
        a.pay_amount,
        sum(pay_amount) over(order by month) pay_amount
from(
        select 
                month(dt) month,
                sum(pay_amount) pay_amount
        from
                user_trade
                where year(dt)=2018
                group by month(dt)
     ) a;

在这里插入图片描述
现在需要计算出2017-2018年每月的支付总额和当年累积支付总额:

select
        a.year,
        a.month,
        a.pay_amount,
        sum(a.pay_amount) over(partition by a.year order by a.month)
from
        (
        select
                year(dt) year,
                month(dt) month,
                sum(pay_amount) pay_amount
        from
                user_trade
                where year(dt) in (2017,2018)
                group by year(dt),month(dt)
        )a;        

在这里插入图片描述
注意:
1、partition by : 起到了分组的作用
2、order by:按照什么顺序进行累加,升序ASC,降序DESC,默认升序

2、avg() over()

现在需要计算2018年每个月的近3个月的平均支付金额:

select
        a.month,
        a.pay_amount,
        avg(a.pay_amount) over(order by a.month rows between 2 preceding and current row)
from
        (select
                month(dt) month,
                sum(pay_amount) pay_amount
        from
                user_trade
                where year(dt)=2018
                group by month(dt)
        )a;

在这里插入图片描述

3、语法总结

sum(…A…) over(partition by …B… order by …C… rows between …D1… and …D2…)
avg(…A…) over(partition by …B… order by …C… rows between …D1… and …D2…)

A:需要被加工的字段名称
B:分组的字段名称
C:排序的字段名称
D:计算的行数范围

rows between unbounded preceding and current row :代表包括本行和之前所有的行
rows between current row and unbounded following :包括本行和之后所有的行
rows between 3 preceding and current row : 包括本行以内和前三行
rows between 3 preceding and 1 following:从前三行到下一行(一共5行)

二、分区排序窗口函数

分区排序窗口函数有三个,分别是:
1、row_number() over(partition by A order by B)
2、rank() over(partition by A order by B)
3、dense_rank() over(partition by A order by B)
其中A代表分区的字段名称,B代表排序的字段名称

三者区别:
row_number:它会为查询出来的每一行记录生成一个序号,依次排序且不会重复
rank:排序后的记录值相同的都标记相同的序号,临近的不相同的记录值按之前相同的记录值的个数加1,就是rank排序之后的序号是不连续的
dense_rank:排序后的记录值相同的都标记相同的序号,临近不相同的记录值也按照之前的序号加1,也就是这个排序后的序号总是连续的

例:现在需要计算2019年1月,用户购买的商品品类数量的排名

select
        user_name,
        count(distinct goods_category),
        row_number() over(order by count(distinct goods_category)),
        rank() over(order by count(distinct goods_category)),
        dense_rank() over(order by count(distinct goods_category))
from
        user_trade
        where substr(dt,1,7)='2019-01'
        group by user_name;

在这里插入图片描述
例:选出2019年支付金额排名在第10、20、30名的用户

select
        a.user_name,
        a.pay_amount,
        a.rank
from
        (        
        select
                user_name,
                sum(pay_amount) pay_amount,
                rank() over(order by sum(pay_amount) desc) rank
        from
                user_trade
                where year(dt)=2019
                group user_name
        )a where a.rank in (10,20,30);

在这里插入图片描述

三、分组排序窗口函数

ntile(n) over(partition by …A… order by …B…)
n:切分的片数
A:分组的字段名称
B:排序的字段名称

注意:
1、ntile(n):用于将分组数据按照顺序分成n片,返回当前切片值
2、ntile不支持rows between
3、如果切片不均匀,默认增加第一个分片的分布

例:将2019年1月的支付用户,按照支付金额分成5组

select
        user_name,
        sum(pay_amount) pay_amount,
        ntile(5) over(order by sum(pay_amount) desc) level
from
        user_trade
        where substr(dt,1,7)='2019-01'
        group by user_name;

在这里插入图片描述
例:选出2019年退款金额排名前10%的用户
在这里插入图片描述

select
        a.user_name,
        a.refund_amount,
        a.level
from
        (
        select
                user_name,
                sum(refund_amount) refund_amount,
                ntile(10) over(order by sum(refund_amount) desc) level
        from
                user_refund
                where year(dt)=2019
                group by user_name
        )a 
        where a.level=1;     

在这里插入图片描述

四、偏移分析窗口函数

1、lag(…) over(…)
2、lead(…) over(…)

Lag和Lead分析函数可以在同一次查询中取出同一字段的前N行的数据(Lag)和后N行的数据(Lead)作为独立的列。
在实际应用当中,若要用到取今天和昨天的某字段差值时,Lag和Lead函数的应用就显得尤为重要。

lag(exp_str,offset,defval) over(partiton by … order by …)
lead(exp_str,offset,defval) over(partition by … order by …)
1、exp_str是字段名称
2、offset是偏移量。当使用lag时,假设当前行在表中排在第5行,而offset为3,则表示我们所要找的数据行就是表中的第2行(即5-3=2)。默认值为1。
3、defval是默认值。当两个函数取上N或下N个值时,当在表中从当前行向前数N行已经超出了表的范围时,就defval作为函数的返回值,若没有指定返回值,则返回NULL。

例如:用户Alice和Alexander的各种时间偏移
1、lag()

select
        user_name,
        dt,
        lag(dt,1,dt) over(partition by user_name order by dt),
        lag(dt) over(partition by user_name order by dt),
        lag(dt,2,dt) over(partition by user_name order by dt),
        lag(dt,2) over(partition by user_name order by dt)
from
        user_trade
        where dt>'0' and user_name in ('Alice','Alexander');

在这里插入图片描述

2、lead()

select
        user_name,
        dt,
        lead(dt,1,dt) over(partition by user_name order by dt),
        lead(dt) over(partition by user_name order by dt),
        lead(dt,2,dt) over(partition by user_name order by dt),
        lead(dt,2) over(partition by user_name order by dt)
from
        user_trade
        where dt>'0' and user_name in ('Alice','Alexander');

在这里插入图片描述
例:支付时间间隔超过100天的用户数

select 
        count(distinct user_name)
from        
        (
        select
                user_name,
                dt,
                lead(dt) over(partition by user_name order by dt) lead_dt
        from
                user_trade
                where dt>'0'
        )a 
        where a.lead_dt is not null 
        and datediff(a.lead_dt,a.dt)>100;

三、练习

四、参考文章

上述部分数据及sql参考自开课吧视频,视频链接丢失
Hive 窗口函数

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:28:56  更:2021-08-11 12:31:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 13:40:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码