hive开窗函数over(partition by ......)用法

本文介绍Hive SQL中over(partition by...)与group by的区别及应用场景,通过示例展示如何使用over(partition by...)进行分组聚合,并与group by进行对比,突出over(partition by...)在保持原始数据完整性方面的优势。

一、over(partition by ......)主要和聚合函数sum()、count()、avg()等结合使用,实现分组聚合的功能

示列:根据day_id日期和mac_id机器码进行聚合分组求每一天的该机器的销量和即sum_num,hive sql语句:select day_id,mac_id,mac_color,day_num,sum(day_num)over(partition by day_id,mac_id order by day_id) sum_num from test_temp_mac_id;

注:day_id,mac_id,mac_color,day_num为查询原有数据,sum_num为计算结果

day_idmac_idmac_colorday_numsum_num
201710111292金色189
201710111292金色1489
201710111292金色289
201710111292金色1189
201710111292黑色289
201710111292粉金5889
201710111292金色189
201710112013金色1022
201710112013金色922
201710112013金色222
201710112013金色122
201710121292金色518
201710121292金色718
201710121292金色518
201710121292粉金118
201710122013粉金17
201710122013金色67
201710131292黑色11
201710132013粉金22
2017101112460茶花金11


二、over(partition by ......)与group by 区别

如果用group by实现一中根据day_id日期和mac_id机器码进行聚合分组求每一天的该机器的销量和即sum_num,

则hive sql语句为:select day_id,mac_id,sum(day_num) sum_num from test_temp_mac_id group by day_id,mac_id order by day_id;结果如下表

注:我们可以观察到group by可以实现同样的分组聚合功能,但sql语句不能写与分组聚合无关的字段,否则会报错,即group by 与over(partition by ......)主要区别为,带上group by的hive sql语句只能显示与分组聚合相关的字段,而带上over(partition by ......)的hive sql语句能显示所有字段.。

day_idmac_idsum_num
201710111246091
201710112013022
201710111292289
201710121292218
20171012201307
20171013129221
20171013201302




### Hive 开窗函数边界处理方式 在 Hive 中,开窗函数的边界可以通过 `ROWS BETWEEN` 和 `RANGE BETWEEN` 来定义窗口范围。这些关键字允许用户根据业务需求精确控制窗口的起始和结束位置。以下是关于边界处理的具体使用方法: #### 1. 关键字含义 - **CURRENT ROW**:表示当前行。 - **UNBOUNDED PRECEDING**:表示从窗口的第一行开始(无上界)。 - **UNBOUNDED FOLLOWING**:表示到窗口的最后一行结束(无下界)。 - **PRECEDING**:向前指定行数。 - **FOLLOWING**:向后指定行数。 - **[num] PRECEDING**:表示当前行之前的 `[num]` 行。 - **[num] FOLLOWING**:表示当前行之后的 `[num]` 行。 #### 2. 语法结构 开窗函数的边界范围可以通过以下语法定义: ```sql (ROWS | RANGE) BETWEEN (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING) ``` #### 3. 常见边界设置 - **从第一行到当前行**: ```sql SUM(A) OVER (PARTITION BY B ORDER BY C ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) ``` 这种方式适用于需要计算累积值的场景[^4]。 - **从当前行到最后一行**: ```sql SUM(A) OVER (PARTITION BY B ORDER BY C ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) ``` - **固定窗口大小**: - 包括当前行及其前两行: ```sql SUM(A) OVER (PARTITION BY B ORDER BY C ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) ``` - 包括当前行及其前后各一行(共三行): ```sql SUM(A) OVER (PARTITION BY B ORDER BY C ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) ``` - **默认窗口范围**: - 当未指定窗口从句时,默认为 `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`[^3]。 - 如果同时缺少 `ORDER BY` 和窗口从句,则默认为 `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING`。 #### 4. 示例代码 以下是一个完整的示例,展示如何使用不同的边界条件: ```sql -- 示例数据 CREATE TABLE sales ( user_name STRING, month_id INT, sale_amt DECIMAL(10, 2) ); INSERT INTO sales VALUES ('Alice', 1, 100.0), ('Alice', 2, 200.0), ('Alice', 3, 300.0), ('Bob', 1, 50.0), ('Bob', 2, 75.0), ('Bob', 3, 100.0); -- 查询示例 SELECT user_name, month_id, sale_amt, -- 累积求和(从第一行到当前行) SUM(sale_amt) OVER (PARTITION BY user_name ORDER BY month_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sum, -- 固定窗口(当前行及其前两行) AVG(sale_amt) OVER (PARTITION BY user_name ORDER BY month_id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS avg_last_3_months FROM sales; ``` #### 5. `ROWS` 和 `RANGE` 的区别 - **ROWS**:基于物理行数进行窗口划分。 - **RANGE**:基于排序字段的值进行窗口划分。如果排序字段存在重复值,则这些行会被视为同一逻辑行[^2]。 例如: ```sql -- 使用 ROWS SUM(A) OVER (PARTITION BY B ORDER BY C ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) -- 使用 RANGE SUM(A) OVER (PARTITION BY B ORDER BY C RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) ``` 在 `RANGE` 模式下,如果 `C` 的值相同,则这些行会被合并为一个逻辑行参与计算。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值