Hive开窗函数的进阶SQL案例

一、开窗函数基础

1. ​定义与作用

开窗函数(Window Functions)在保留原始行数据的同时,对分组内的行进行聚合或排序分析,常用于累计计算、排名、移动平均等场景。与普通聚合函数(如SUMAVG)的区别在于:

  • 普通聚合函数:每组返回一行(行数减少)。
  • 开窗函数:每组返回多行(保留原始行数)。
2. ​核心语法结构
复制代码
函数名() OVER (
    [PARTITION BY 列1, 列2...]  -- 分组依据
    [ORDER BY 列A [ASC|DESC]]   -- 排序依据
    [ROWS BETWEEN 范围]         -- 窗口范围
)
  • **PARTITION BY**:按列分组,函数在每个分组内独立计算(如按省份分组)。
  • **ORDER BY**:分组内按列排序,影响窗口范围逻辑(如时间升序)。
  • **ROWS BETWEEN**:指定窗口边界,常见选项如下表:
范围关键字 含义
UNBOUNDED PRECEDING 起点行(分区第一行)
CURRENT ROW 当前行
n PRECEDING 前n行
n FOLLOWING 后n行
UNBOUNDED FOLLOWING 终点行(分区最后一行)

默认行为说明​:

  • 仅用 PARTITION BY → 窗口为整个分组(UNBOUNDED PRECEDING TO UNBOUNDED FOLLOWING)。
  • PARTITION BY + ORDER BY → 窗口为起点到当前行(UNBOUNDED PRECEDING TO CURRENT ROW

二、累计计算场景

1. ​年度招聘人数累加
sql 复制代码
WITH t1 AS (
  SELECT SUBSTR(hiredate, 1, 4) AS year FROM emp
),
t2 AS (
  SELECT year, COUNT(*) AS cnt 
  FROM t1 GROUP BY year
)
SELECT 
  year, 
  cnt,
  SUM(cnt) OVER (ORDER BY year) AS cumulative_cnt  -- 按年份滚动累加
FROM t2;

结果说明​:

year cnt cumulative_cnt
2023 50 50
2024 80 130
2025 70 200

三、排名分析场景

3. ​并列排名处理
sql 复制代码
SELECT 
  name, class, score,
  ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num,  -- 连续唯一序号
  RANK() OVER (ORDER BY score DESC) AS rank,          -- 并列跳号(1,1,3)
  DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank -- 并列不跳号(1,1,2)
FROM Scores;

排名函数对比​:

分数 row_num rank dense_rank
95 1 1 1
95 2 1 1
90 3 3 2

四、移动计算场景

4. ​1日移动平均销售额
sql 复制代码
SELECT 
  shop, day, sales,
  AVG(sales) OVER (
    ORDER BY day 
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW  -- 限定窗口为当前行及前2行
  ) AS avg_3day 
FROM daily_sales;

结果片段​:

day sales avg_3day
2025-01-01 200 200.0
2025-01-02 300 250.0
2025-01-03 250 250.0
4. 2​相邻行差值计算
sql 复制代码
SELECT 
  record_date, temperature,
  temperature - LAG(temperature, 1) OVER (ORDER BY record_date) AS diff  -- 今日与昨日温差
FROM weather;

五、连续行为分析

5. ​用户连续登录统计
sql 复制代码
-- 步骤1:生成连续性标识
WITH t1 AS (
  SELECT 
    user_id, login_date,
    DATE_SUB(login_date, INTERVAL ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) DAY) AS grp
  FROM logins
)
-- 步骤2:聚合连续区间
SELECT 
  user_id,
  MIN(login_date) AS start_date,
  MAX(login_date) AS end_date,
  COUNT(*) AS consecutive_days
FROM t1
GROUP BY user_id, grp;

输出说明​:

user_id start_date end_date consecutive_days
1001 2025-01-01 2025-01-05 5
1001 2025-01-07 2025-01-08 2

六、高级偏移分析

6.1 ​会话最新未读消息提取
sql 复制代码
WITH RankedMessages AS (
  SELECT 
    from_id, to_id, msg, isRead, time,
    ROW_NUMBER() OVER (
      PARTITION BY from_id, to_id 
      ORDER BY time DESC
    ) AS rn  -- 按会话分组,时间倒序排
  FROM chat_history
)
SELECT from_id, to_id, msg
FROM RankedMessages
WHERE rn = 1 AND isRead = 0;  -- 取最新且未读的消息
6.2 ​计算登录间隔天数
sql 复制代码
SELECT 
  user_id, start_date, end_date,
  DATEDIFF(
    start_date, 
    LAG(end_date, 1) OVER (PARTITION BY user_id ORDER BY start_date)
  ) - 1 AS gap_days  -- 本次开始日期与上次结束日期的间隔
FROM login_sessions;

七、分区聚合控制

7. ​动态计算组内极值
sql 复制代码
SELECT 
  id, val,
  MAX(val) OVER (
    PARTITION BY id 
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) AS group_max  -- 分组内全局最大值
FROM test;

结果特点​:同一分组的所有行显示相同的最大值。


附:核心函数适用场景总结

场景 推荐函数 关键子句
累计求和 SUM() OVER(ORDER BY) ORDER BY 定义累加顺序
组内排名 DENSE_RANK() OVER(PARTITION BY) PARTITION BY 分组依据
移动平均 AVG() OVER(ROWS BETWEEN n PRECEDING) ROWS BETWEEN 限定窗口范围
相邻记录比较 LAG()/LEAD() 偏移量参数控制前后行
连续性行为分析 ROW_NUMBER() + 日期差值 生成连续性标识列

提示:实际开发中需注意

  1. 性能优化 :避免全分区无边界窗口(如 UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),优先用 ROWS 限定物理范围
  2. 空值处理LAG/LEAD 的第三个参数可设置默认值(如 LAG(col,1,0)
相关推荐
ptc学习者1 小时前
oracle logwr,ckpt,dbwn 如何协同工作的
数据库·sql
计算机毕设残哥4 小时前
基于Hadoop+Spark的商店购物趋势分析与可视化系统技术实现
大数据·hadoop·python·scrapy·spark·django·dash
IT研究室4 小时前
大数据毕业设计选题推荐-基于大数据的全球能源消耗量数据分析与可视化系统-大数据-Spark-Hadoop-Bigdata
大数据·hadoop·spark·毕业设计·源码·数据可视化·bigdata
lifallen9 小时前
Flink SQL 查询 核心概念与实战指南
大数据·数据库·sql·flink
还是奇怪10 小时前
SQL注入的“无影脚”:详解空格绕过WAF的N种方法
数据库·sql·安全·web安全
xcg34012311 小时前
Spring boot中 限制 Mybatis SQL日志的大字段输出
spring boot·sql·mybatis·大字段打印
孟意昶1 天前
Spark专题-第三部分:性能监控与实战优化(1)-认识spark ui
大数据·数据仓库·sql·ui·spark·etl
大叔_爱编程1 天前
基于Hadoop的美妆产品网络评价的数据采集与分析-django+spider
大数据·hadoop·django·毕业设计·源码·课程设计·美妆产品
Q26433650231 天前
【有源码】基于Hadoop+Spark的豆瓣电影数据分析与可视化系统-基于大数据的电影评分趋势分析与可视化系统
大数据·hadoop·python·数据分析·spark·毕业设计·课程设计
阿巴~阿巴~1 天前
MySQL复合查询(重点)
服务器·数据库·sql·mysql·ubuntu