区间累计统计是按动态范围(如过去7天、值在[x-10,x+10]内)对每行计算聚合,核心在于窗口边界依当前行值或时间戳动态划定;ROWS按物理行偏移,RANGE按实际值/时间划界,二者语义不同。

什么是区间累计统计?
区间累计统计不是简单地 SUM() 整列,而是对每个数据点,计算它在某个动态范围(比如“过去7天”“前3行”“值在 [x-10, x+10] 内”)内的聚合结果。核心在于窗口边界不固定,依赖当前行的值或时间戳动态划定。
ROWS BETWEEN 和 RANGE BETWEEN 的关键区别
很多人写错就卡在这儿:用 ROWS 想实现数值区间,结果得到的是物理行数偏移,和业务逻辑脱节。
-
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW:只看位置,不管order by列的值是否连续 -
RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW(PostgreSQL/Oracle)或RANGE BETWEEN 10 PRECEDING AND CURRENT ROW(MySQL 8.0+,要求ORDER BY列是数字):按实际值划界,才叫“区间” - SQLite 不支持
RANGE的数值/时间表达式,只能退化为ROWS+ 子查询
MySQL 8.0 实现「过去30天销量累计」的写法
假设表 sales 有 sale_date DATE 和 amount DECIMAL,要为每条记录算“截至当天、过去30天内(含)的总销量”:
SELECT
sale_date,
amount,
SUM(amount) OVER (
ORDER BY sale_date
RANGE BETWEEN INTERVAL 29 DAY PRECEDING AND CURRENT ROW
) AS cum_30d
FROM sales;
注意:INTERVAL 29 DAY PRECEDING 是因为 CURRENT ROW 自身已包含当天,往前推29天才能凑满30天整。如果用 30 DAY PRECEDING,实际是31天。
系统设置:密码修改 增加用户(权限) [打印机设置 票样打印设置 这2块用不着实现系统界面上 放着就好了]基础设置:基础参数设置(买票设置/订票设置/退票设置)(比如多少时间之前不能买票订票) 车票设置(标准票/儿童票/。。。增删改) 车辆设置(增删该) 车次设置(增删该) 运营计划设置(调度设置)前台营业:销售车票
当数据库不支持 RANGE 时间偏移时怎么办?
比如 SQL Server 2019 或旧版 MySQL,RANGE 只接受数字字面量,不认 INTERVAL。这时得用自连接或相关子查询:
SELECT s1.sale_date, s1.amount, (SELECT SUM(s2.amount) FROM sales s2 WHERE s2.sale_date BETWEEN DATE_SUB(s1.sale_date, INTERVAL 29 DAY) AND s1.sale_date) AS cum_30d FROM sales s1;
性能会明显下降,尤其数据量大时。必须确保 sale_date 有索引;如果允许近似结果,可考虑先按天聚合再窗口计算,减少行数。
真正难的不是语法,是想清楚“区间”到底由什么定义——是日历天数?自然月?还是数值带宽?选错语义,再对的 SQL 也跑不出正确结果。









