Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >开窗函数 spark sql实现累加、累积计数、累乘

开窗函数 spark sql实现累加、累积计数、累乘

作者头像
数据仓库晨曦
发布于 2025-03-04 06:22:15
发布于 2025-03-04 06:22:15
20900
代码可运行
举报
文章被收录于专栏:数据仓库技术数据仓库技术
运行总次数:0
代码可运行

前面对开窗函数做了基础知识介绍,今天我们对其应用做详细介绍。通过开窗函数实现累积求和(累加),累积计数,累乘(累积相乘)。

有一定难度,建议先思考然后再阅读

1.样例数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-----+-----------+---------+-------------+
| id  | group_id  | amount  |   c_date    |
+-----+-----------+---------+-------------+
| 1   | a         | 1.00    | 2025-01-01  |
| 2   | a         | 1.00    | 2025-01-02  |
| 3   | a         | 2.00    | 2025-01-03  |
| 4   | a         | 3.00    | 2025-01-03  |
| 5   | b         | -1.00   | 2025-01-01  |
| 6   | b         | 1.00    | 2025-01-02  |
| 7   | b         | 0.50    | 2025-01-03  |
| 8   | b         | 2.00    | 2025-01-03  |
| 9   | b         | 1.00    | 2025-01-03  |
+-----+-----------+---------+-------------+

建表语句及数据插入语句

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE t_accure
(
    id       BIGINT,
    group_id STRING,
    amount   decimal(16, 2),
    c_date   STRING
);

INSERT INTO t_accure
VALUES (1,'a',1,'2025-01-01'),
       (2,'a',1,'2025-01-02'),
       (3,'a',2,'2025-01-03'),
       (4,'a',3,'2025-01-03'),
       (5,'b',-1,'2025-01-01'),
       (6,'b',1,'2025-01-02'),
       (7,'b',0.5,'2025-01-03'),
       (8,'b',2,'2025-01-03'),
       (9,'b',1,'2025-01-03');

2. 累加

题目

按照group_id进行分组,根据c_date顺序从早到晚对amount进行累积求和。

累加有两种方式,在对于排序相同的数据进行累加的时候,由于排序相同(且随机),所以出现两种方式:1.计算到当前行;2.计算到与当前排序值相同的最后一行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id,
       group_id,
       amount,
       c_date,
       sum(amount)
           over (partition by group_id order by c_date rows between unbounded preceding and current row) as accure_add1,
        sum(amount)
           over (partition by group_id order by c_date range between unbounded preceding and current row) as accure_add2,
        sum(amount)
           over (partition by group_id order by c_date) as accure_add3
from t_accure

执行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-----+-----------+---------+-------------+--------------+--------------+--------------+
| id  | group_id  | amount  |   c_date    | accure_add1  | accure_add2  | accure_add3  |
+-----+-----------+---------+-------------+--------------+--------------+--------------+
| 1   | a         | 1.00    | 2025-01-01  | 1.00         | 1.00         | 1.00         |
| 2   | a         | 1.00    | 2025-01-02  | 2.00         | 2.00         | 2.00         |
| 3   | a         | 2.00    | 2025-01-03  | 4.00         | 7.00         | 7.00         |
| 4   | a         | 3.00    | 2025-01-03  | 7.00         | 7.00         | 7.00         |
| 5   | b         | -1.00   | 2025-01-01  | -1.00        | -1.00        | -1.00        |
| 6   | b         | 1.00    | 2025-01-02  | 0.00         | 0.00         | 0.00         |
| 7   | b         | 0.50    | 2025-01-03  | 0.50         | 3.50         | 3.50         |
| 8   | b         | 2.00    | 2025-01-03  | 2.50         | 3.50         | 3.50         |
| 9   | b         | 1.00    | 2025-01-03  | 3.50         | 3.50         | 3.50         |
+-----+-----------+---------+-------------+--------------+--------------+--------------+

注意:

  • 1.注意第3行和4行的结果;
  • 2.注意滴7,8,9行的结果;
  • 3.注意窗口框架方位省略后的结果:accure_add3

3.累积计数

题目 1.按照group_id进行分组,根据c_date顺序从早到晚对c_date进行累积计数; 2.按照group_id进行分组,根据c_date顺序从早到晚对c_date进行累积计数,要求去重;

3.1累积计数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id,
       group_id,
       amount,
       c_date,
       count(c_date)
             over (partition by group_id order by c_date rows between unbounded preceding and current row )  as accure_count1,
       count(c_date)
             over (partition by group_id order by c_date range between unbounded preceding and current row ) as accure_count2,
       count(c_date)
             over (partition by group_id order by c_date )                                                   as accure_count3
from t_accure

执行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-----+-----------+---------+-------------+----------------+----------------+----------------+
| id  | group_id  | amount  |   c_date    | accure_count1  | accure_count2  | accure_count3  |
+-----+-----------+---------+-------------+----------------+----------------+----------------+
| 1   | a         | 1.00    | 2025-01-01  | 1              | 1              | 1              |
| 2   | a         | 1.00    | 2025-01-02  | 2              | 2              | 2              |
| 3   | a         | 2.00    | 2025-01-03  | 3              | 4              | 4              |
| 4   | a         | 3.00    | 2025-01-03  | 4              | 4              | 4              |
| 5   | b         | -1.00   | 2025-01-01  | 1              | 1              | 1              |
| 6   | b         | 1.00    | 2025-01-02  | 2              | 2              | 2              |
| 7   | b         | 0.50    | 2025-01-03  | 3              | 5              | 5              |
| 8   | b         | 2.00    | 2025-01-03  | 4              | 5              | 5              |
| 9   | b         | 1.00    | 2025-01-03  | 5              | 5              | 5              |
+-----+-----------+---------+-------------+----------------+----------------+----------------+

3.2 累积去重计数

我们首先想到的是直接使用count(disitnct amount) 的方式来完成,注意:在hive中支持count(distinct amount)over() 这种方式,但是在spark中不支持这种写法.

count(distinct amount)over()方式实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id,
       group_id,
       amount,
       c_date,
       count(distinct c_date)
           over (partition by group_id order by c_date rows between unbounded preceding and current row ) as accure_count
from t_accure

collect_set方式实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id,
       group_id,
       amount,
       c_date,
       size(c_date_set) as accure_count
from (select id,
             group_id,
             amount,
             c_date,
             collect_set(c_date)
                         over (partition by group_id order by c_date rows between unbounded preceding and current row ) as c_date_set
      from t_accure) t

执行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-----+-----------+---------+-------------+---------------+
| id  | group_id  | amount  |   c_date    | accure_count  |
+-----+-----------+---------+-------------+---------------+
| 1   | a         | 1.00    | 2025-01-01  | 1             |
| 2   | a         | 1.00    | 2025-01-02  | 2             |
| 3   | a         | 2.00    | 2025-01-03  | 3             |
| 4   | a         | 3.00    | 2025-01-03  | 3             |
| 5   | b         | -1.00   | 2025-01-01  | 1             |
| 6   | b         | 1.00    | 2025-01-02  | 2             |
| 7   | b         | 0.50    | 2025-01-03  | 3             |
| 8   | b         | 2.00    | 2025-01-03  | 3             |
| 9   | b         | 1.00    | 2025-01-03  | 3             |
+-----+-----------+---------+-------------+---------------+

4.累乘(累积相乘)

题目 按照group_id进行分组,根据c_date顺序从早到晚对amount进行累积相乘;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select id,
       group_id,
       amount,
       c_date,
       amount_list,
       aggregate(amount_list, cast(1 as decimal(16, 2)), (amount_list, x) -> cast(amount_list * x as decimal(16,
                 2))) as accure_mul
from (select id,
             group_id,
             amount,
             c_date,
             collect_list(amount)
                          over (partition by group_id order by c_date rows between unbounded preceding and current row ) as amount_list
      from t_accure) t
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-----+-----------+---------+-------------+------------------------------+-------------+
| id  | group_id  | amount  |   c_date    |         amount_list          | accure_mul  |
+-----+-----------+---------+-------------+------------------------------+-------------+
| 1   | a         | 1.00    | 2025-01-01  | [1.00]                       | 1.00        |
| 2   | a         | 1.00    | 2025-01-02  | [1.00,1.00]                  | 1.00        |
| 3   | a         | 2.00    | 2025-01-03  | [1.00,1.00,2.00]             | 2.00        |
| 4   | a         | 3.00    | 2025-01-03  | [1.00,1.00,2.00,3.00]        | 6.00        |
| 5   | b         | -1.00   | 2025-01-01  | [-1.00]                      | -1.00       |
| 6   | b         | 1.00    | 2025-01-02  | [-1.00,1.00]                 | -1.00       |
| 7   | b         | 0.50    | 2025-01-03  | [-1.00,1.00,0.50]            | -0.50       |
| 8   | b         | 2.00    | 2025-01-03  | [-1.00,1.00,0.50,2.00]       | -1.00       |
| 9   | b         | 1.00    | 2025-01-03  | [-1.00,1.00,0.50,2.00,1.00]  | -1.00       |
+-----+-----------+---------+-------------+------------------------------+-------------+

5 涉及函数

  • sum https://sparkfunctions.com/sum
  • count https://sparkfunctions.com/count
  • collect_set https://sparkfunctions.com/collect_set
  • collect_list https://sparkfunctions.com/collect_list
  • aggregate https://sparkfunctions.com/aggregate
  • size https://sparkfunctions.com/size
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据仓库技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
详解spark开窗函数
窗口函数(Window functions)又称分析函数或开窗函数,它允许你在不改变原始行的情况下,对一组相关的行(称为“窗口”)进行计算和分析。与普通的聚合函数(如SUM、AVG等)不同,窗口函数不会将多行合并为一行,而是为每一行返回一个计算结果,同时保留原始行的详细信息。通常写法为func()over(),详细语法如下:
数据仓库晨曦
2025/02/26
1682
详解spark开窗函数
常见大数据面试SQL-max_by(x,y)处理缺失值
现有用户账户表,包含日期、用户id、用户余额,其中用户余额发生了缺失,需要进行补全。补全规则:如果余额为空则取之前最近不为空值进行填补。如果截止到最早日期都为空则补0;
数据仓库晨曦
2024/08/01
2570
常见大数据面试SQL-max_by(x,y)处理缺失值
最强总结!数据库开窗函数完全指南!!
开窗函数(Window Functions)是SQL中强大的分析工具,允许我们在不改变结果集行数的情况下进行复杂的聚合和分析操作。本文将系统地介绍开窗函数的用法和实际应用场景。
SQL数据库开发
2024/11/12
6390
最强总结!数据库开窗函数完全指南!!
深入MySQL窗口函数:原理和应用
窗口函数(Window Functions)是SQL标准中的一个高级特性,它允许用户在不改变查询结果集行数的情况下,对每一行执行聚合计算或其他复杂的计算。这些计算是基于当前行与结果集中其他行之间的关系进行的。窗口函数特别适用于需要执行跨多行的计算,同时又想保持原始查询结果集的行数不变的场景。
公众号:码到三十五
2024/03/19
3.2K0
深入MySQL窗口函数:原理和应用
正宗的ClickHouse开窗函数来袭("开窗函数")
由于公众号不再按时间线推送,如果不想错过精彩内容,请在关注公众号后,点击右上角 ... 设为星标,感谢支持。
Nauu
2021/03/10
9.6K0
最强最全面的大数据SQL面试题和答案(由31位大佬共同协作完成)
本套SQL题的答案是由许多大佬共同贡献,1+1的力量是远远大于2的,有不少题目都采用了非常巧妙的解法,也有不少题目有多种解法。本套大数据SQL题不仅题目丰富多样,答案更是精彩绝伦!
五分钟学大数据
2021/12/27
5.3K0
SQL题目
2、   • 当签到天数%7=3 则领取3金币   • 当签到天数%7=0 则领取7金币   • 其余情况,领取1金币
挽风
2023/10/17
3230
SQL系列(一)快速掌握Hive查询的重难点
作为一名数(取)据(数)分(工)析(具)师(人),不得不夸一下SQL,毕竟凭一己之力养活了80%的数据分析师,甚至更多。SQL语言短小精悍,简单易学,而且分析师重点只关注查询,使得学习成本和时间成本瞬间就下来了。
HsuHeinrich
2023/02/24
3.3K0
SQL系列(一)快速掌握Hive查询的重难点
Spark SQL/Hive实用函数大全
本篇文章主要介绍Spark SQL/Hive中常用的函数,主要分为字符串函数、JSON函数、时间函数、开窗函数以及在编写Spark SQL代码应用时实用的函数算子五个模块。
大数据学习与分享
2020/12/31
5.2K0
Hive函数
**CONCAT_WS(separator, str1, str2,...):**多字符串拼接
ha_lydms
2023/11/19
5241
Hive函数
Pandas 2.2 中文官方教程和指南(四)
由于许多潜在的 pandas 用户对 SQL 有一定的了解,本页旨在提供使用 pandas 执行各种 SQL 操作的一些示例。
ApacheCN_飞龙
2024/04/26
5470
Pandas 2.2 中文官方教程和指南(四)
Hive的利器:强大而实用的开窗函数
与聚合函数类似,开窗函数也是对行集组进行聚合计算。但是它不像普通聚合函数那样,每组通常只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计算的行集组是窗口。
大数据学习与分享
2021/04/22
3.6K0
Hive的利器:强大而实用的开窗函数
(文末有福利)使用collec_list、collect_set函数进行行转列
该函数是非确定性的,因为收集结果的顺序取决于行的顺序,这在经过shuffle之后可能是不确定的。
数据仓库晨曦
2024/08/12
2010
(文末有福利)使用collec_list、collect_set函数进行行转列
【Hive】SQL语句大全
继承 org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
全栈程序员站长
2022/08/30
2.6K0
大数据技术之_08_Hive学习_03_查询+函数
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Select 查询语句语法:
黑泽君
2019/03/11
1.9K0
大数据技术之_08_Hive学习_03_查询+函数
如何用SQL实现用户行为漏斗分析
1 每日活跃设备明细 dwd_start_log--->dws_uv_detail_day
大数据学习与分享
2022/05/19
2.3K0
如何用SQL实现用户行为漏斗分析
数据仓库开发 SQL 使用技巧总结
作者:dcguo 使用 sql 做数仓开发有一段时间了,现做一下梳理复盘,主要内容包括 sql 语法、特性、函数、优化、特殊业务表实现等。 mysql 数据结构 常用 innodb 存储为 B+ 树 特点 多路平衡树,m 个子树中间节点就包含 m 个元素,一个中间节点是一个 page(磁盘页) 默认 16 kb; 子节点保存了全部得元素,父节点得元素是子节点的最大或者最小元素,而且依然是有序得; 节点元素有序,叶子节点双向有序,便于排序和范围查询。 优势 平衡查找树,logn 级别 crud; 单一节点比二
腾讯技术工程官方号
2022/07/19
3.3K0
数据仓库开发 SQL 使用技巧总结
数据分析面试必考—SQL快速入门宝典
SQL全称Structured Query Language,说人话就是结构化查询语言。毫不夸张地说,它是数据分析必会技能Top1,因为没有哪个初级数据分析师的面试能跨过SQL技能考核这一项的。
用户8612862
2021/05/13
4.6K0
数据分析面试必考—SQL快速入门宝典
滴滴大数据面试SQL-截止目前登陆用户数及登陆用户列表
已知有用户登录记录表包含登录日期和登录用户ID,请查询出截止到当前日期累积登录用户数及登陆用户列表
数据仓库晨曦
2024/06/27
1810
滴滴大数据面试SQL-截止目前登陆用户数及登陆用户列表
Hive SQL 大厂必考常用窗口函数及相关面试题
二、窗口函数的基本用法 1.基本语法 2.设置窗口的方法 1)window_name 2)partition by 子句 3) order by子句 4)rows 指定窗口大小 3.开窗函数中加order by 和 不加 order by的区别
王知无-import_bigdata
2022/11/11
3.9K0
Hive SQL 大厂必考常用窗口函数及相关面试题
推荐阅读
相关推荐
详解spark开窗函数
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验