如何编写SQL查询获取按公司和产品分组的最近7张发票平均价格
问题分析与修正方案
你的原SQL逻辑存在核心错误,具体问题:
- 子查询先取了全表最近7条记录,而非每个
(Company, Product_Code)组内的最近7条,完全偏离需求 GROUP BY中包含price,会把同公司同产品但价格不同的行拆分成多个分组,无法得到正确的组内平均值HAVING里的公司过滤可以提前放到WHERE中,提升查询效率
正确解法(使用窗口函数)
利用窗口函数ROW_NUMBER()给每个分组内的记录按发票日期倒序编号,筛选出每组前7条后再计算平均值,同时注意将字符串格式的发票日期转换为日期类型,避免排序错误:
MySQL 8.0+ 版本
SELECT company, product_code, AVG(price) AS avg_recent_7_price FROM ( SELECT *, -- 按公司+产品分组,每组内按发票日期倒序编号 ROW_NUMBER() OVER ( PARTITION BY company, product_code ORDER BY STR_TO_DATE(invoice_date, '%d%m%Y') DESC ) AS row_num FROM your_table_name -- 提前过滤目标公司,减少计算量 WHERE company IN ('A', 'B', 'C') ) AS ranked_records -- 筛选每组最近7条记录 WHERE row_num <= 7 -- 仅按公司和产品分组计算平均值 GROUP BY company, product_code;
其他数据库适配说明
- PostgreSQL:将日期转换函数改为
TO_DATE(invoice_date, 'DDMMYYYY') - SQL Server:将日期转换函数改为
CONVERT(date, invoice_date, 103)(假设发票日期格式为日/月/年)
核心逻辑保持一致,仅日期转换函数随数据库方言调整。
逻辑拆解
- 子查询通过
PARTITION BY company, product_code将数据拆分为独立的公司-产品分组 ORDER BY STR_TO_DATE(...) DESC确保每个分组内最新的发票排在最前面,编号为1- 外层筛选
row_num <=7,保留每个分组的最近7条记录 - 最后按公司和产品分组,计算这7条记录的价格平均值
内容的提问来源于stack exchange,提问作者Jake1204
相关产品推荐
相关产品推荐

