Hive 按区间条件 分组统计

本文介绍如何使用Hive进行按区间条件的数据分组统计,包括按重量区间和时间间隔进行分组的方法,并提供具体实例。

Hive 按区间条件 分组统计

数据准备

-- 建表
CREATE TABLE `site_trans`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `site` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `price` decimal(10, 2) NULL DEFAULT NULL,
  `weight` double NOT NULL DEFAULT 0,
  `created_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
);
-- 数据插入
INSERT INTO `site_trans` VALUES (1, '上海', 65.50, 11, '2022-12-01 10:03:04');
INSERT INTO `site_trans` VALUES (2, '上海', 89.40, 9, '2022-12-01 10:08:50');
INSERT INTO `site_trans` VALUES (3, '上海', 89.40, 13, '2022-12-01 10:18:50');
INSERT INTO `site_trans` VALUES (4, '上海', 89.40, 23, '2022-12-01 10:18:10');
INSERT INTO `site_trans` VALUES (5, '上海', 89.40, 33, '2022-12-01 10:38:10');

请添加图片描述

按 区间条件 分组统计

按重量段 分区统计:

-- 按重量区间统计:
SELECT
	site,
	substring(created_time,1,10) datestr,
	sum(price) as total_price,
	floor( weight / 10 ) * 10 AS weight_duration 
FROM
	`site_trans` 
GROUP BY
	site,
	substring(created_time,1,10),
	floor( weight / 10 ) * 10;

请添重量区间统计加图片描述
按时间段 分区统计:

-- 按间隔n分钟统计:10分钟 (2022-12-05 00:00:03数据问题未处理,拼接时间字符串时可处理)
SELECT
	site,
	format_time,
	sum( price ),
	sum( weight ) 
FROM
	(
	SELECT
		site,
		price,
		weight,
		date_format( concat( DATE ( created_time ), ' ', HOUR ( created_time ), ':', floor( MINUTE ( created_time )/ 10 )* 10 ), '%y-%m-%d %h:%i:%s' ) AS format_time 
	FROM
		`site_trans` 
	) res 
GROUP BY
	site,
	format_time 
ORDER BY
	format_time;

请添加图片描述

### Hive 窗口函数中的窗口区间使用方法 Hive 窗口函数支持通过 `ROWS` 或 `RANGE` 子句来指定窗口的大小和范围,这使得可以灵活控制计算的数据集范围。当未显式声明 `ORDER BY` 和 `WINDOW` 子句时,默认情况下窗口会覆盖整个分区内的所有记录[^5]。 #### ROWS 和 RANGE 的区别 - **ROWS**: 基于物理行数定义窗口边界。例如,可以通过指定前 N 行或后 N 行来调整窗口范围。 - **RANGE**: 基于逻辑值(通常是有序字段上的值差)定义窗口边界。它依赖于 `ORDER BY` 字段的值差异而非实际行数。 以下是具体的语法结构: ```sql OVER ( PARTITION BY col_name ORDER BY order_col [ROWS|RANGE {BETWEEN start AND end}] ) ``` 其中: - `PARTITION BY`: 定义分组依据。 - `ORDER BY`: 定义排序依据。 - `start/end`: 可以为 `CURRENT ROW`, `UNBOUNDED PRECEDING`, 或者 `N PRECEDING/FOLLOWING`. #### 示例:基于 ROWS 的窗口区间 假设有一张表 `video_play_log` 记录用户的播放行为,包含以下字段: - `category`: 视频类别 - `play_progress`: 用户观看百分比 (0~1) 目标是计算每类视频中当前用户与其他最近两行用户的平均播放进度。 ```sql SELECT category, play_progress, AVG(play_progress) OVER ( PARTITION BY category ORDER BY play_progress DESC ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) AS avg_progress FROM video_play_log; ``` 此查询会在每个分类下按照播放进度降序排列,并取当前行及其之前的两行作为窗口进行均值计算[^3]。 #### 示例:基于 RANGE 的窗口区间 如果希望基于播放进度的实际数值差距而不是固定行数,则可改用 `RANGE`: ```sql SELECT category, play_progress, COUNT(*) OVER ( PARTITION BY category ORDER BY play_progress ASC RANGE BETWEEN 10 PRECEDING AND CURRENT ROW ) AS count_within_range FROM video_play_log; ``` 这里假定 `play_progress` 是连续型变量,上述语句将统计同一类别里所有与当前播放进度相差不超过10个百分点的所有记录数量。 需要注意的是,在某些数据库实现中,对于非唯一键值的情况,`RANGE`可能会导致重复计数问题;而`ROWS`则严格按照行号操作,不会出现此类情况。 --- ### 解决相关问题 针对题目提到的需求——找出播放进度超过60%的类别并返回其平均播放进度(保留两位小数),可通过如下方式完成: ```sql WITH filtered_data AS ( SELECT category, ROUND(AVG(play_progress), 2) AS avg_progress FROM video_play_log WHERE play_progress >= 0.6 GROUP BY category ) SELECT * FROM filtered_data ORDER BY avg_progress DESC; ``` 该脚本先筛选出符合条件的日志条目,再聚合求得各分类下的平均值最后依顺序展示结果[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值