SQL滚动求和

需求1:滚动计算10月每天 当天至+25天 范围内 总配货门店数和箱数
  1. 基础表:对底表聚合去重,将日期转为日期格式
sql 复制代码
-- 天商品仓库 门店配货表
DROP TABLE IF EXISTS h_tmp.tmp_base ;
CREATE TABLE h_tmp.tmp_base AS
SELECT
    TO_DATE(order_time) as dt
    ,h_code  -- 商品编码
    ,wrh_name -- 仓库名称
    ,shop_code -- 配货门店
    ,sum(stock_box) as inflow_qty -- 配货箱数
FROM  base 
WHERE dt =DATE_SUB(CURRENT_DATE,1)) 
AND is_send=1
AND DATE_FORMAT(order_time,'yyyy-MM-dd') BETWEEN  '2025-10-01' AND '2025-10-31' 
GROUP BY TO_DATE(order_time),wrh_name,shop_code,h_code
;

-- 取10-01的数,方便后面验证
SELECT COUNT(DISTINCT shop_code) as shop_cnt
,SUM(inflow_qty) as inflow_qty 
FROM h_tmp.tmp_dw_inflow_di_251117
WHERE dt BETWEEN '2025-10-01' AND '2025-10-26'
AND h_code = '123456'
AND wrh_name = '上海仓'
  1. 滚动求和

    • 窗口版 使用 range 限制范围
      PRECEDING 之前
      FOLLOWING 之后
    • 自连接版 限制连接表日期范围
sql 复制代码
-- dt 为统计批次日
-- inflow_26d_shop_cnt 为当天+未来 25 天商品各仓配货总门店数
-- inflow_26d_qty 为当天+未来 25 天商品各仓配货总箱数
-- 方法一 窗口版
DROP TABLE IF EXISTS h_tmp.tmp_ans;
CREATE TABLE h_tmp.tmp_ans AS
SELECT  DISTINCT 
        dt,
        h_code,
        wrh_name,
        SUM(IF(rn=1,1,0)) OVER (PARTITION BY h_code, wrh_name
                                ORDER BY dt --UNIX_TIMESTAMP(dt)
                                RANGE BETWEEN CURRENT ROW AND 25 FOLLOWING) AS inflow_26d_shop_cnt,
        COUNT(DISTINCT shop_code) OVER (PARTITION BY h_code, wrh_name
                                ORDER BY dt 
                                RANGE BETWEEN CURRENT ROW AND 25 FOLLOWING) AS inflow_26d_shop_cnt2,
        SUM(inflow_qty)   OVER (PARTITION BY h_code, wrh_name
                                ORDER BY dt 
                                RANGE BETWEEN CURRENT ROW AND 25 FOLLOWING) AS inflow_26d_qty
FROM (
        SELECT  dt,
                h_code,
                wrh_name,
                shop_code,
                inflow_qty,
                ROW_NUMBER() OVER (PARTITION BY h_code, wrh_name,shop_code
                                   ORDER BY dt) AS rn -- 每个商品仓库门店 根据时间顺序标记,在滚动计算时只计算首次出现的门店
        FROM    h_tmp.tmp_base 
) t
;

--  验证结果与步骤1是否一致
SELECT * 
FROM   h_tmp.tmp_ans
WHERE dt = '2025-10-01'
AND h_code = '123456'
AND wrh_name = '上海仓'

-- 方法二 自连接
DROP TABLE IF EXISTS h_tmp.tmp_ans2;
CREATE TABLE h_tmp.tmp_ans2 AS
SELECT
    t1.dt
    ,t1.h_code
    ,t1.wrh_name
    ,COUNT(DISTINCT t2.shop_code) AS inflow_26d_shop_cnt
    ,SUM(t2.inflow_qty)           AS inflow_26d_qty
FROM (
    -- 先把起点压成 (dt,h_code,wrh_name) 唯一行,再自连接(26 天滚动)
    SELECT dt, h_code, wrh_name
    FROM   h_tmp.tmp_base 
    GROUP  BY dt, h_code, wrh_name
) t1
LEFT JOIN h_tmp.tmp_base t2
ON t1.h_code   = t2.h_code
AND t1.wrh_name = t2.wrh_name
AND t2.dt BETWEEN t1.dt AND date_add(t1.dt,25)
GROUP BY t1.dt, t1.h_code, t1.wrh_name;

--  验证结果与步骤1是否一致
SELECT * 
FROM   h_tmp.tmp_ans2
WHERE dt = '2025-10-01'
AND h_code = '123456'
AND wrh_name = '上海仓'


-- 方法三 自连接 + if
DROP TABLE IF EXISTS h_tmp.tmp_ans3;
CREATE TABLE h_tmp.tmp_ans3 AS
SELECT
    t1.dt
    ,t1.h_code
    ,t1.wrh_name
    ,COUNT(DISTINCT if(t2.dt BETWEEN t1.dt AND date_add(t1.dt,25),t2.shop_code,null)) AS inflow_26d_shop_cnt
    ,SUM(if(t2.dt BETWEEN t1.dt AND date_add(t1.dt,25),t2.inflow_qty,0)  )         AS inflow_26d_qty
FROM (
    -- 先把起点压成 (dt,h_code,wrh_name) 唯一行,再自连接(26 天滚动)
    -- t1 侧同一天如果有 N 行(哪怕完全相同的门店),就会把 t2 的箱数重复加 N 次
    SELECT dt, h_code, wrh_name
    FROM   h_tmp.tmp_base 
    GROUP  BY dt, h_code, wrh_name
) t1
LEFT JOIN h_tmp.tmp_base t2
ON t1.h_code   = t2.h_code
AND t1.wrh_name = t2.wrh_name
GROUP BY t1.dt, t1.h_code, t1.wrh_name;

--  验证结果与步骤1是否一致
SELECT * 
FROM   h_tmp.tmp_ans3
WHERE dt = '2025-10-01'
AND h_code = '123456'
AND wrh_name = '上海仓'
需求2 入库时间滚动25天配货门店数和箱数
sql 复制代码
DROP TABLE IF EXISTS h_tmp.wh_in ;
CREATE TABLE h_tmp.wh_in AS
SELECT
    DATE_FORMAT(order_time,'yyyy-MM-dd') as dt  -- 入库时间
    ,h_code  -- 商品编码
    ,wrh_name -- 入库仓库(wrh_name)
    ,DATE_ADD(order_time,25) as dt_25 -- 25天后的时间
FROM  h_dw.stock_im--入库
WHERE dt = '2025-11-17' 
AND qty>0
AND DATE_FORMAT(order_time,'yyyy-MM-dd') BETWEEN  '2025-10-01' AND '2025-11-01' 
GROUP BY DATE_FORMAT(order_time,'yyyy-MM-dd'),DATE_ADD(order_time,25)
,wrh_name,h_code
;

SELECT  
    a.h_code
    ,a.wrh_name
    ,a.dt
    ,a.dt_25
    ,COUNT(distinct if(b.dt BETWEEN a.dt AND a.dt_25,b.shop_code,null) ) AS inflow_26d_shop_cnt --入库后25天内的配货门店数
    ,SUM(if(b.dt BETWEEN a.dt AND a.dt_25 , b.inflow_qty,0)) AS inflow_26d_qty  --入库后25天内的配货箱数
FROM h_tmp.wh_in a   -- 天商品仓库 入库表
LEFT JOIN h_tmp.tmp_base b  -- 天商品仓库 配货门店表
ON a.h_code = b.h_code AND a.wrh_name = b.wrh_name 
GROUP BY a.h_code
    ,a.wrh_name
    ,a.dt
    ,a.dt_25
;

相关链接:

  1. MySQL 8.0 参考手册 _ 窗口函数框架规范
相关推荐
阳光九叶草LXGZXJ8 小时前
达梦数据库-报错-15-列【XXX】长度超出定义
linux·运维·数据库·sql·学习
字节渡客8 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
OnlineProxy10 小时前
亚马逊多账号运营:如何在规避“关联封号”风险的同时实现电商规模化扩张
服务器·数据库·redis
辻弋20112 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
可乐鸡翅yeah_13 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
石头麻辣鱼13 小时前
Bamboo 调度系统 OceanBase 适配实战:存储过程迁移踩过的三个大坑
数据库
龙亘川13 小时前
数智驱动民政升级 精准守护民生保障
大数据·数据库·人工智能
念何架构之路14 小时前
zap扩展生态与总结
java·前端·数据库
晚安日记wanna14 小时前
MySQL 回表为什么这么慢?5 种优化手段逐个拆解
数据库·mysql·性能优化
第七页独白14 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库