向前滚动累加SQL 实现思路

一、业务背景

在经营分析场景里,我们经常需要回答:

  • “截至今天,过去 N 天/月/周累计发生了多少?”

  • “把维度切到省、市、房型、项目经理、代理商等,结果又是什么?”

本文用两个真实需求做演示:

  1. 以天为粒度,计算过去 7 天 的放款单量、放款金额;并顺便给出过去 5 天 的口径作为对比。

  2. 以月为粒度,计算过去 6 个月(含当月)的累计订单数,维度为代理商。

为了便于阅读,下文所有表名、字段名都做了脱敏混淆,但逻辑 100 % 保留。


二、需求 1:过去 7 天放款(天粒度,多维度)

2.1 期望输出

data_date…(其它维度)loan_cntloan_amtys_fst_apply_cnt_7sumdelivery_go_capacity_sum

其中:

  • ys_fst_apply_cnt_7sum = 过去 7 天(不含当日)的同维度放款单量之和

  • delivery_go_capacity_sum = 过去 7 天(不含当日)的同维度放款金额之和

2.2 实现思路

采用 自关联(self-join)

  • 主表 A:取当日维度切片;

  • 从表 B:在时间窗口 [A.data_date-7, A.data_date-1] 且维度完全一致的数据;

  • SUM() 聚合即可完成累加。

2.3 关键 SQL

SELECTa.data_date,a.dim_province,a.dim_city,a.dim_town,a.dim_roof1,a.dim_roof2,a.dim_pm,a.dim_dealer,a.dim_dealer_team,a.dim_settle,a.cnt_当天单量,a.amt_当天金额,/* 过去 7 天(不含当日)累计 */SUM(COALESCE(b.cnt_当天单量,0)) AS cnt_7d,SUM(COALESCE(b.amt_当天金额,0)) AS amt_7d,/* 过去 5 天(不含当日)累计,仅作演示 */SUM(CASE WHEN a.data_date - b.data_date <= 5 THEN COALESCE(b.cnt_当天单量,0) ELSE 0 END) AS cnt_5d,SUM(CASE WHEN a.data_date - b.data_date <= 5 THEN COALESCE(b.amt_当天金额,0) ELSE 0 END) AS amt_5d
FROM fact_daily_loan a
LEFT JOIN fact_daily_loan bON (COALESCE(a.dim_province,' ')   = COALESCE(b.dim_province,' ')AND COALESCE(a.dim_city,' ')       = COALESCE(b.dim_city,' ')AND COALESCE(a.dim_town,' ')       = COALESCE(b.dim_town,' ')AND COALESCE(a.dim_roof1,' ')      = COALESCE(b.dim_roof1,' ')AND COALESCE(a.dim_roof2,' ')      = COALESCE(b.dim_roof2,' ')AND COALESCE(a.dim_pm,' ')         = COALESCE(b.dim_pm,' ')AND COALESCE(a.dim_dealer,-1)      = COALESCE(b.dim_dealer,-1)AND COALESCE(a.dim_dealer_team,-1) = COALESCE(b.dim_dealer_team,-1)AND COALESCE(a.dim_settle,' ')     = COALESCE(b.dim_settle,' ')AND a.data_date - b.data_date BETWEEN 1 AND 7   -- 关键:滑窗 7 天
)
GROUP BYa.data_date,a.dim_province,a.dim_city,a.dim_town,a.dim_roof1,a.dim_roof2,a.dim_pm,a.dim_dealer,a.dim_dealer_team,a.dim_settle,a.cnt_当天单量,a.amt_当天金额;

2.4 注意点

  1. 维度对齐:所有维度都要 COALESCE 以防 NULL 匹配不上。

  2. 时间区间a.data_date - b.data_date BETWEEN 1 AND 7 等价于“前 7 天不含当日”。

  3. 性能:如果数据量大,建议把日期过滤下推、或在从表加索引 (date, 维度组合)


三、需求 2:过去 6 月订单(月粒度,仅代理商维度)

3.1 期望输出

report_monthdealer_namedealer_idcnt_6m

3.2 实现思路

采用 生成月份序列 + 预聚合 的经典写法:

  1. 先把事实表出现的所有月份抽出来(去重)。

  2. 为每个月生成一个 6 个月窗口(含自己 + 前 5 个月)。

  3. 预先把订单按月去重,得到 (dealer, month, order_no) 的干净集合。

  4. 用窗口月把“干净集合”挂上去,再 COUNT(DISTINCT order_no) 即可。

3.3 关键 SQL

-- 1. 提取事实表所有月份
WITH months AS (SELECT DISTINCT date_trunc('month', confirm_dt) AS month_startFROM fact_order_detail
),-- 2. 为每个月生成 6 个月窗口
windowed AS (SELECTm.month_start,generate_series(m.month_start - INTERVAL '5 month',m.month_start,INTERVAL '1 month')::date AS window_monthFROM months m
),-- 3. 预聚合:按月去重订单
base AS (SELECTdealer_name,dealer_id,date_trunc('month', confirm_dt) AS month_start,order_noFROM fact_order_detail
),-- 4. 把窗口拼到 base 上
agg AS (SELECTw.month_start      AS report_month,b.dealer_name,b.dealer_id,COUNT(DISTINCT b.order_no) AS cnt_6mFROM windowed wJOIN base bON b.month_start = w.window_monthGROUP BYw.month_start,b.dealer_name,b.dealer_id
)-- 5. 最终输出
SELECTcnt_6m,dealer_name,dealer_id,to_char(report_month, 'YYYY-MM-DD') AS report_month_str
FROM agg
ORDER BYdealer_id,report_month;

3.4 注意点

  • generate_series 生成月份序列,天然避开了闰月、大小月问题。

  • 预先把订单按月去重,避免后面 COUNT DISTINCT 时扫大表。

  • 如果窗口更大(如 12 个月),可把 5 改成 11 即可。


四、两种方案对比与选型建议

维度7 天放款(自关联)6 月订单(生成序列)
粒度
窗口7 天6 个月
维度多(省/市/房型…)少(仅代理商)
数据量百万/千万级千万级
主要算子Self-Join + SUMgenerate_series + JOIN + COUNT DISTINCT
性能敏感点维度组合基数高导致笛卡尔放大月份序列膨胀有限,可接受
适用场景任意维度、短周期滚动累加维度单一、长周期滚动累加

一句话总结:

  • 短周期 + 高维度 → 自关联 + 时间过滤;

  • 长周期 + 低维度 → 预聚合 + 生成序列。


五、扩展思考

  1. Presto/Trino 可用 RANGE BETWEEN INTERVAL '7' DAY PRECEDING AND 1 DAY PRECEDING 的窗口函数,逻辑更简洁,但引擎需要支持。

  2. ClickHouse 可用 GROUP BY (date, dim...) WITH ROLLUP + runningAccumulate 实现实时累加。

  3. 实时场景 可以把窗口结果写到 Redis / Druid,再通过 API 提供毫秒级查询。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/90645.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/90645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI(14)——文本分块优化

RAG时&#xff0c;检索效果的优劣&#xff0c;和文本的分块的情况有很大关系。SpringAI中通过TokenTextSplitter对文本分块。本文对SpringAI提供的TokenTextSplitter源码进行了分析&#xff0c;并给出一些自己的想法&#xff0c;欢迎大家互相探讨。查看了TokenTextSplitter的源…

Python----大模型(RAG 的智能评估-LangSmith)

一、LangSmith LangSmith是LangChain的一个子产品&#xff0c;是一个大模型应用开发平台。它提供了从原 型到生产的全流程工具和服务&#xff0c;帮助开发者构建、测试、评估和监控基于LangChain 或其他 LLM 框架的应用程序。 安装 LangSmith pip install langsmith0.1.137 官网…

磁悬浮轴承转子不平衡质量控制策略设计:原理、分析与智能实现

磁悬浮轴承(Active Magnetic Bearing, AMB)以其无接触、无摩擦、高转速、无需润滑等革命性优势,在高端旋转机械领域(如高速电机、离心压缩机、飞轮储能、航空航天动力系统)展现出巨大潜力。然而,转子固有的质量不平衡是AMB系统面临的核心挑战之一,它诱发强同步振动,威胁…

C++查询mysql数据

文章目录 文章目录 1.前言 2. 代码 &#xff08;1&#xff09;执行查询SQL &#xff08;2&#xff09;获取结果集 &#xff08;3&#xff09;遍历结果集&#xff08;获取字段数、行数&#xff09; &#xff08;4&#xff09;释放资源 3.完整代码 1.前言 我们成功连接数…

【论文阅读】-《GenAttack: Practical Black-box Attacks with Gradient-Free Optimization》

GenAttack&#xff1a;利用无梯度优化的实用黑盒攻击 Moustafa Alzantot UCLA Los Angeles, U.S.A malzantotucla.edu Yash Sharma Cooper Union New York, U.S.A sharma2cooper.edu Supriyo Chakraborty IBM Research New York, U.S.A supriyous.ibm.com Huan Zhang UCLA Los…

CT、IT、ICT 和 DICT区别

这四个术语&#xff1a;CT、IT、ICT 和 DICT&#xff0c;是信息通信行业中常见的核心概念&#xff0c;它们既有演进关系&#xff0c;又有各自的技术重点。&#x1f539; 一、CT&#xff08;Communication Technology&#xff09;通信技术**定义&#xff1a;**以语音通信为核心的…

Effective C++ 条款4:确定对象被使用前已先被初始化

Effective C 条款4&#xff1a;确定对象被使用前已先被初始化核心思想&#xff1a;永远在使用对象前将其初始化。未初始化对象是未定义行为的常见来源&#xff0c;尤其对于内置类型。 1. 内置类型手动初始化 int x 0; // 手动初始化 const char* text &quo…

LangSmith的配置介绍

文章目录注册及登录生成API KeyLangSmith的配置方式一&#xff1a;放运行环境里方式二&#xff1a;写代码里执行代码查看LangSmith上是否看到本次运行的项目记录LangSmith的其他注意注册及登录 首先使用邮箱注册一个账号及设置密码&#xff0c;等收到收到邮件后&#xff0c;进…

Linux的生态与软件安装

坚持用 清晰易懂的图解 代码语言&#xff0c;让每个知识点变得简单&#xff01; &#x1f680;呆头个人主页详情 &#x1f331; 呆头个人Gitee代码仓库 &#x1f4cc; 呆头详细专栏系列 座右铭&#xff1a; “不患无位&#xff0c;患所以立。” Linux的生态与软件安装前言目录…

3.4 安全-分布式-数据库-挖掘

一、数据库的安全数据库里面的安全措施&#xff1a;用户标识和鉴定&#xff1a;用户的账户口令等存取控制&#xff1a;对用户操作进行控权&#xff0c;有对应权限码才能操作。密码存储和传输&#xff1a;加密存储。视图的保护&#xff1a;视图需要授权审计&#xff1a;专门的文…

多线程 Reactor 模式

目录 多线程 Reactor 模式的核心动机 多线程演进方向 多线程 Reactor 模型结构 多线程 EchoServer 实现核心部分 Handler 的多线程化 多线程 Reactor 的三个核心点 本篇文章内容的前置知识为 单线程 Reactor 模式&#xff0c;如果不了解&#xff0c;可点击链接学习 单线程…

[NLP]多电源域设计的仿真验证方法

多电源域设计的仿真验证方法 1. 更复杂的 Testbench 例子(多电源域、复杂低功耗场景) 假设有两个电源域 PD1 和 PD2,分别对应控制信号 pwr_sw_ctrl1、iso_ctrl1、ret_ctrl1 和 pwr_sw_ctrl2、iso_ctrl2、ret_ctrl2,且两域之间有通信。 RTL 端口声明(简化版) module top…

Apache Ignite 中 WHERE 子句中的子查询(Subqueries in WHERE Clause)的执行方式

这段内容是关于 Apache Ignite 中 WHERE 子句中的子查询&#xff08;Subqueries in WHERE Clause&#xff09;的执行方式 的说明。理解这段内容对于编写高效的 SQL 查询、避免性能瓶颈非常重要。下面我将为你 逐句解释并深入理解这段内容。&#x1f9fe; 原文翻译 解释 原文&a…

MySQL(153)如何使用全文索引?

MySQL的全文索引&#xff08;Full-Text Index&#xff09;是一种特殊的索引类型&#xff0c;专门用于加速文本数据的搜索。与普通的B树索引不同&#xff0c;全文索引适用于大文本字段&#xff08;如TEXT、VARCHAR等&#xff09;的全文搜索。它通过构建一个倒排索引&#xff0c;…

微分方程入门之入门之入门,纯笔记

当描述 相对变化量 比 绝对量 更容易时&#xff0c;微分方程就经常用到了。 比如&#xff0c;描述为什么种群数量增加or减少【相对】&#xff0c;比描述为什么它在某个时间点是某个特定值【绝对】更容易。 物理学中&#xff0c;运动经常用力来描述&#xff0c;力–>代表变化…

【C++】简单学——vector类(模拟实现)

模拟实现的准备工作 看源码&#xff0c;了解这个类的大概组成 1.先看成员变量 成员变量的组成是三个迭代器 问&#xff1a;这个iterator内嵌类型究竟是什么&#xff1f;即这个迭代器是什么 迭代器实际就是T* 问&#xff1a;这三个迭代器代表什么意思&#xff1f; 连蒙带猜…

【WRF】根据自动安装脚本安装 WRF / WRF-CHEM等

目录 GitHub 上 WRF 自动安装脚本 ⚙️ 脚本的作用 🖥️ 支持的系统 📦 可安装的 WRF 版本及其选项 ✅ 如何使用(以 WRF 4.6.1 为例) ✅ 依赖库的安装位置 完整安装脚本分析 参考 GitHub 上 WRF 自动安装脚本 GitHub 上的 WRF-Install-Script 项目的 Releases(发布版本…

M²IV:面向大型视觉-语言模型中高效且细粒度的多模态上下文学习

MIV&#xff1a; Towards Efficient and Fine-grained Multimodal In Context Learning in Large Vision-Language Models COLM 2025 why 新兴的研究方向&#xff1a;上下文学习&#xff08;ICL&#xff09;的效果“向量化”&#xff0c;其核心思想是用transformer内部的向量来…

龙迅#LT8711UXD适用于Type-C/DP1.4 /EDP转 HDMI2.0 功能,分辨率高达4K60HZ,可支持HDCP!

1. 描述LT8711UXD 是一款高性能双通道 Type-C/DP1.4 转 HDMI2.0 转换器&#xff0c;旨在将 USB Type-C 源或 DP1.4 源连接到 HDMI2.0 接收器。该LT8711UXD集成了一个符合 DP1.4 标准的接收器和一个符合 HDMI2.0 标准的发射器。此外&#xff0c;还嵌入了两个用于CC通信的CC控制器…

《计算机组成原理与汇编语言程序设计》实验报告一 基本数字逻辑及汉字显示

目 录 一、实验学时 二、实验目的 三、实验要求 四、实验内容 五、实验步骤 1、打开Logisim软件&#xff0c;列出异或逻辑电路真值表&#xff0c;并使用与、或、非基本原件实现异或逻辑电路。 2、打开Logisim软件&#xff0c;列出同或逻辑电路真值表&#xff0c;并使用…