需求1:滚动计算10月每天 当天至+25天 范围内 总配货门店数和箱数
- 基础表:对底表聚合去重,将日期转为日期格式
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 = '上海仓'
-
滚动求和
- 窗口版 使用 range 限制范围
PRECEDING 之前
FOLLOWING 之后 - 自连接版 限制连接表日期范围
- 窗口版 使用 range 限制范围
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
;
相关链接: