SQL思路解析:窗口滑动的应用

目录

🎯 问题目标

第一步:从数据中我们能直接得到什么?

第二步:我们想要的“7天窗口”长什么样?

第三步:SQL 怎么表达“某一天的前六天”?

🔍JOIN 比窗口函数更灵活

第四步:每个窗口要计算什么?

第五步:怎么避免不满 7 天的窗口?

最终完整 SQL


表: Customer+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| customer_id   | int     |
| name          | varchar |
| visited_on    | date    |
| amount        | int     |
+---------------+---------+
在 SQL 中,(customer_id, visited_on) 是该表的主键。
该表包含一家餐馆的顾客交易数据。
visited_on 表示 (customer_id) 的顾客在 visited_on 那天访问了餐馆。
amount 是一个顾客某一天的消费总额。

你是餐馆的老板,现在你想分析一下可能的营业额变化增长(每天至少有一位顾客)。

计算以 7 天(某日期 + 该日期前的 6 天)为一个时间段的顾客消费平均值。average_amount 要 保留两位小数。

结果按 visited_on 升序排序。

返回结果格式的例子如下。

示例 1:输入:
Customer 表:
+-------------+--------------+--------------+-------------+
| customer_id | name         | visited_on   | amount      |
+-------------+--------------+--------------+-------------+
| 1           | Jhon         | 2019-01-01   | 100         |
| 2           | Daniel       | 2019-01-02   | 110         |
| 3           | Jade         | 2019-01-03   | 120         |
| 4           | Khaled       | 2019-01-04   | 130         |
| 5           | Winston      | 2019-01-05   | 110         | 
| 6           | Elvis        | 2019-01-06   | 140         | 
| 7           | Anna         | 2019-01-07   | 150         |
| 8           | Maria        | 2019-01-08   | 80          |
| 9           | Jaze         | 2019-01-09   | 110         | 
| 1           | Jhon         | 2019-01-10   | 130         | 
| 3           | Jade         | 2019-01-10   | 150         | 
+-------------+--------------+--------------+-------------+
输出:
+--------------+--------------+----------------+
| visited_on   | amount       | average_amount |
+--------------+--------------+----------------+
| 2019-01-07   | 860          | 122.86         |
| 2019-01-08   | 840          | 120            |
| 2019-01-09   | 840          | 120            |
| 2019-01-10   | 1000         | 142.86         |
+--------------+--------------+----------------+
解释:
第一个七天消费平均值从 2019-01-01 到 2019-01-07 是restaurant-growth/restaurant-growth/ (100 + 110 + 120 + 130 + 110 + 140 + 150)/7 = 122.86
第二个七天消费平均值从 2019-01-02 到 2019-01-08 是 (110 + 120 + 130 + 110 + 140 + 150 + 80)/7 = 120
第三个七天消费平均值从 2019-01-03 到 2019-01-09 是 (120 + 130 + 110 + 140 + 150 + 80 + 110)/7 = 120
第四个七天消费平均值从 2019-01-04 到 2019-01-10 是 (130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86

 来源:Leecode


🎯 问题目标

先问自己最本质的问题:

 我想得到的到底是什么?

你想得到:

  • 某一天(比如 2019-01-07)为 窗口最后一天

  • 以它为终点往前推 6 天(共 7 天)的所有消费数据

  • 求这 7 天的总消费额和平均消费额(平均保留两位小数)

  • 然后按日期升序列出每个窗口的情况

第一步:从数据中我们能直接得到什么?

我们原始数据是:

| customer_id | name  | visited_on | amount |
|-------------|-------|------------|--------|
| 1           | Jhon  | 2019-01-01 | 100    |
| 2           | Daniel| 2019-01-02 | 110    |
| ...         | ...   | ...        | ...    |

这是“按顾客”记录的交易数据。

原始数据是“每个顾客某天消费了多少”,而我们不关心顾客是谁,只关心 每一天总共有多少消费。 

为了达成这个目标,你最小的可操作单位是:

✅ 每一天的“总营业额”

所以,第一步我们应该做的是:

SELECTvisited_on,SUM(amount) AS total_amount
FROM Customer
GROUP BY visited_on

 得到了:

| visited_on | total_amount |
|------------|--------------|
| 2019-01-01 | 100          |
| 2019-01-02 | 110          |
| 2019-01-03 | 120          |
| ...        | ...          |

第二步:我们想要的“7天窗口”长什么样?

比如你想分析 2019-01-07 这个窗口,它包括:

  • 2019-01-01

  • 2019-01-02

  • 2019-01-03

  • 2019-01-04

  • 2019-01-05

  • 2019-01-06

  • 2019-01-07

我们要把这 7 天的金额加总后求平均。

换句话说,对于每一个日期 D,你要去找所有日期 D',满足:

D' >= D - 6 天 AND D' <= D,然后求 sum(amount)

第三步:SQL 怎么表达“某一天的前六天”?

想象一下,窗口要对比谁和谁?

我们要让每一行(例如日期是 2019-01-10)“看见”自己之前 6 天的数据。但 SQL 是面向集合的语言,每一行默认不能看见其他行。

怎么让一行“看到”它前面的几天?答案是:自连接(JOIN)!

SELECTc1.visited_on,             -- 作为窗口的当前“右端点”c2.visited_on,             -- 被扫描比较的行
FROM (SELECT visited_on, SUM(amount) AS daily_totalFROM CustomerGROUP BY visited_on
) c1
JOIN (SELECT visited_on, SUM(amount) AS daily_totalFROM CustomerGROUP BY visited_on
) c2ON c2.visited_on BETWEEN DATE_SUB(c1.visited_on, INTERVAL 6 DAY) AND c1.visited_on

这个 JOIN 的意思是:

对于每一行 c1,找出所有 c2,使得 c2.visited_on 落在 c2 之前 6 天之内。

也就是说,每一行 c1 会配对出一个 7 天的“时间窗口”数据集 c2。

就像下面这个例子:

c1.visited_onc2.visited_on(符合条件)
2019-01-072019-01-01 ~ 2019-01-07
2019-01-082019-01-02 ~ 2019-01-08
2019-01-092019-01-03 ~ 2019-01-09
2019-01-102019-01-04 ~ 2019-01-10

你可以理解为:“c1 的每一天”,都配对了“过去七天的 c2”,这就模拟出“滑动窗口”的行为了!

🔍JOIN 比窗口函数更灵活

在“时间窗口”这种分析中,数据可能并不是每天都有,或者每天不止一条记录,比如:

| visited_on   | amount |
|--------------|--------|
| 2024-01-01   | 100    |
| 2024-01-01   | 80     |
| 2024-01-03   | 200    |

这种不连续、一天多条的情况,用 OVER (ORDER BY visited_on ROWS ...) 是不靠谱的,因为行数 ≠ 时间!

JOIN 这种方式,直接按时间范围配对,不依赖数据是否连续,每天有多少条都不影响。

第四步:每个窗口要计算什么?

你想要的就是:

  • c1.visited_on:当前窗口的最后一天

  • SUM(c2.amount):这 7 天的总金额

  • ROUND(SUM(c2.amount) / 7, 2):这 7 天的平均值(保留两位小数)

第五步:怎么避免不满 7 天的窗口?

比如当你分析 2019-01-02 时,它前面只有两天的数据(01、02),这是 不满 7 天的窗口,要排除掉。

这时候就要加一条语句:

HAVING COUNT(DISTINCT c2.visited_on) = 7

 意思是:只有当这 7 天真的有 7 个不同的日期数据,才纳入最终结果。

最终完整 SQL

把上述分析组合起来,完整 SQL 如下:

SELECT c1.visited_on,SUM(c2.daily_total) AS amount,ROUND(SUM(c2.daily_total)/7, 2) AS average_amount
FROM (SELECT visited_on, SUM(amount) AS daily_totalFROM CustomerGROUP BY visited_on
) c1
JOIN (SELECT visited_on, SUM(amount) AS daily_totalFROM CustomerGROUP BY visited_on
) c2ON c2.visited_on BETWEEN DATE_SUB(c1.visited_on, INTERVAL 6 DAY) AND c1.visited_on
GROUP BY c1.visited_on
HAVING COUNT(c2.visited_on) = 7
ORDER BY c1.visited_on;
问题层级解释
本质问题想知道某天 + 前六天的消费总和和平均
可直接获取的数据每天的顾客消费记录(可汇总)
怎么形成7天窗口用自连接 + 日期范围:BETWEEN D - 6 AND D
如何计算汇总 amount,平均除以 7 并 ROUND
如何过滤不满7天窗口HAVING COUNT(DISTINCT c2.visited_on) = 7
最终排序按 visited_on 升序展示

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

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

相关文章

解决MyBatis参数绑定中参数名不一致导致的错误问题

前言 作为一名Java开发者&#xff0c;我在实际项目中曾多次遇到MyBatis参数绑定的问题。其中最常见的一种情况是&#xff1a;在Mapper接口中定义的参数名与XML映射文件中的占位符名称不一致&#xff0c;导致运行时抛出Parameter xxx not found类异常。这类问题看似简单&#x…

黑马程序员TypeScript课程笔记—类型兼容性篇

类型兼容性的说明 因为传入的时候只有一个参数 对象之间的类型兼容性 接口之间的类型兼容性 函数之间的类型兼容性&#xff08;函数参数个数&#xff09; 和对象的兼容性正好相反 函数之间的类型兼容性&#xff08;函数参数类型&#xff09; 函数参数的兼容性就不要从接口角度…

智能电视的操作系统可能具备哪些优势

丰富的应用资源&#xff1a; 操作系统内置了应用商店&#xff0c;提供了丰富的应用资源&#xff0c;涵盖视频、游戏、教育等多个领域&#xff0c;满足不同用户的多样化需求。用户可以轻松下载并安装所需的应用&#xff0c;享受更多元化的娱乐和学习体验。 流畅的操作体验&…

Xget 正式发布:您的高性能、安全下载加速工具!

您可以通过 star 我固定的 GitHub 存储库来支持我&#xff0c;谢谢&#xff01;以下是我的一些 GitHub 存储库&#xff0c;很有可能对您有用&#xff1a; tzst Xget Prompt Library 原文 URL&#xff1a;https://blog.xi-xu.me/2025/06/02/xget-launch-high-performance-sec…

精美的软件下载页面HTML源码:现代UI与动画效果的完美结合

精美的软件下载页面HTML源码&#xff1a;现代UI与动画效果的完美结合 在数字化产品推广中&#xff0c;一个设计精良的下载页面不仅能提升品牌专业度&#xff0c;还能显著提高用户转化率。本文介绍的精美软件下载页面HTML源码&#xff0c;通过现代化UI设计与丰富的动画效果&…

麒麟v10+信创x86处理器离线搭建k8s集群完整过程

前言 最近为某客户搭建内网的信创环境下的x8s集群&#xff0c;走了一些弯路&#xff0c;客户提供的环境完全与互联网分离&#xff0c;通过yum、apt这些直接拉依赖就别想了&#xff0c;用的操作系统和cpu都是国产版本&#xff0c;好在仍然是x86的&#xff0c;不是其他架构&…

Pycharm的使用技巧总结

目录 一、高效便捷的快捷键 二、界面汉化处理 1.设置 2.插件 3.汉化插件安装 三、修改字体大小、颜色 1.选择文件-设置 2.选择编辑器-配色方案-python 3.修改注释行颜色 4.修改编辑器字体颜色 一、高效便捷的快捷键 序号快捷键功能场景效果1Ctrl /快速注释/取消注释…

安全编码规范与标准:对比与分析及应用案例

在软件开发领域&#xff0c;尤其是涉及安全关键系统的开发中&#xff0c;遵循编码规范和标准是确保软件质量和安全性的重要手段。除了CERT C、CERT Java和MISRA外&#xff0c;还有其他多个与安全相关的编码规范和标准&#xff0c;以下是一些主要标准的对比说明&#xff1a; 一…

FFmpeg学习笔记

1. 播放器的架构 2. 播放器的渲染流程 3. ffmpeg下载与安装 3.0 查看PC是否已经安装了ffmpeg ffmpeg 3.1 下载 wget https://ffmpeg.org/releases/ffmpeg-7.0.tar.gz 3.2 解压 tar zxvf ffmpeg-7.0.tar.gz && cd ./ffmpeg-7.0 3.3 查看配置文件 ./configure …

大宽带怎么做

我有10个G的宽带资源&#xff0c;怎样运行P2P才能将收益巨大化&#xff0c;主要有以下几种方式&#xff1a; 1.多设备汇聚模式&#xff1a;使用多台支持千兆网络的服务器或专用PCDN设备&#xff08;如N1盒子&#xff09;&#xff0c;将10条宽带分别接入不同设备&#xff0c;通过…

pytorch基本运算-导数和f-string

引言 在前序对机器学习的探究过程中&#xff0c;我们已经深刻体会到人工智能到处都有微分求导运算&#xff0c;相关文章链接包括且不限于&#xff1a; BP神经网络 逻辑回归 对于pytorch张量&#xff0c;求导运算必不可少&#xff0c;所以本次就专门来学习一下。 f-string的用…

dvwa4——File Inclusion

LOW: 先随便点开一个文件&#xff0c;可以观察到url栏变成这样&#xff0c;说明?page是dvwa当前关卡用来加载文件的参数 http://10.24.8.35/DVWA/vulnerabilities/fi/?pagefile1.php 我们查看源码 &#xff0c;没有什么过滤&#xff0c;直接尝试访问其他文件 在url栏的pag…

经典面试题:一文了解常见的缓存问题

在面试过程中&#xff0c;面试官的桌子上摆放着很多高频的面试题&#xff0c;能否顺利回答决定了你面试通过的概率。其中缓存问题就是其中的一份&#xff0c;可以说掌握缓存问题及解决方法是面试前必须准备的内容。那么缓存有什么典型的问题&#xff0c;出现的原因是什么&#…

生产环境中安装和配置 Nginx 以部署 Flask 应用的详细指南

在生产环境中部署 Flask 应用时&#xff0c;Nginx 常被用作反向代理服务器&#xff0c;与 WSGI 服务器&#xff08;如 Gunicorn&#xff09;协同工作。Nginx 可以处理静态文件、提供 SSL/TLS 加密、实现负载均衡等功能。本文将详细介绍如何在 Ubuntu/Debian 系统上安装 Nginx&a…

鸿蒙进阶——Mindspore Lite AI框架源码解读之模型加载详解(一)

文章大纲 引言一、模型加载概述二、核心数据结构三、模型加载核心流程 引言 Mindspore 是一款华为开发开源的AI推理框架&#xff0c;而Mindspore Lite则是华为为了适配在移动终端设备上运行专门定制的版本&#xff0c;使得我们可以在OpenHarmony快速实现模型加载和推理等功能&…

AI炼丹日志-24 - MCP 自动操作 提高模型上下文能力 Cursor + Sequential Thinking Server Memory

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇&#xff1a; MyBatis 更新完毕目前开始更新 Spring&#xff0c;一起深入浅出&#xff01; 大数据篇 300&#xff1a; Hadoop&…

【仿muduo库实现并发服务器】实现时间轮定时器

实现时间轮定时器 1.时间轮定时器原理2.项目中实现目的3.实现功能3.1构造定时任务类3.2构造时间轮定时器每秒钟往后移动添加定时任务刷新定时任务取消定时任务 4.完整代码 1.时间轮定时器原理 时间轮定时器的原理类似于时钟&#xff0c;比如现在12点&#xff0c;定一个3点的闹…

Windows10下搭建sftp服务器(附:详细搭建过程、CMD连接测试、连接失败问题分析解决等)

最终连接sftp效果 搭建sftp服务器 1、这里附上作者已找好的 freeSSHd安装包 ,使用它进行搭建sftp服务器。 2、打开freeSSHd安装包,进行安装 (1)、选择完全安装 (2)、安装完成后,对提示窗口选择关闭 (3)、安装完成后,提示是否安装私有密钥。我们选择"是" (4)、安…

推荐几个不错的AI入门学习视频

引言&#xff1a;昨天推荐了几本AI入门书&#xff08;AI入门书&#xff09;&#xff0c;反响还不错。今天&#xff0c;我再推荐几个不错的AI学习视频&#xff0c;希望对大家有帮助。 网上关于AI的学习视频特别多。有收费的&#xff0c;也有免费的。我今天只推荐免费的。 我们按…

点击启动「高效模式」:大腾智能 CAD 重构研发设计生产力

在制造业数字化转型浪潮中&#xff0c;设计工具的革新正成为企业突破效率瓶颈的关键。传统CAD软件因本地硬件依赖、协作壁垒高筑、复杂场景响应迟缓等问题&#xff0c;长期困扰设计团队。 大腾智能CAD依托华为云底座、自研几何引擎及AI技术深度融合&#xff0c;为制造行业各细…