完整教程:【MYSQL】一文读懂 SQL 加权平均价计算:左连接、日期匹配与空值处理

一文读懂 SQL 加权平均价计算:左连接、日期匹配与空值处理

本文通过一个实际的 SQL 查询示例,带你逐步理解如何计算每个产品的加权平均售价,并处理没有销售记录的情况。


查询语句原文

SELECT
Prices.product_id,
IFNULL(
ROUND(
SUM(Prices.price * UnitsSold.units) / SUM(UnitsSold.units),
2
),
0
) AS average_price
FROM Prices
LEFT JOIN UnitsSold
ON Prices.product_id = UnitsSold.product_id
AND UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date
GROUP BY Prices.product_id;

查询逻辑一览

在这里插入图片描述

示例数据表结构

Prices 表(价格表)

product_idpricestart_dateend_date
1102025-01-012025-01-31
1122025-02-012025-02-28
252025-01-012025-12-31

UnitsSold 表(销售表)

product_idpurchase_dateunits
12025-01-152
12025-02-153
22025-03-010
32025-01-015

✅ 查询结果

product_idaverage_price
111.20
20.00

关键点解析

1. 为什么用 LEFT JOIN

  • 为了保留 Prices 表中所有产品,即使它在 UnitsSold 中没有销售记录。
  • 如果用 INNER JOIN,没卖过的产品就不会出现在结果中。

2. ON 条件中的日期范围匹配

ON Prices.product_id = UnitsSold.product_id
AND UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date

这个条件确保:

  • 只将销售记录匹配到其购买日期所在的价格有效期内。
  • 避免将销售记录与错误时间段的价格匹配。
冰棍小例子:
销售日期生效价格是否匹配
6月15日1元
6月15日2元❌(未生效)
7月15日1元❌(已过期)
7月15日2元

如果没有这个日期条件,你会把6月卖的冰棍也按7月的价格算,结果就错了!

3. 加权平均价格计算

SUM(Prices.price * UnitsSold.units) / SUM(UnitsSold.units)
  • 分子:总销售额 = 每个价格 × 对应销售数量的总和
  • 分母:总销售数量
  • 结果就是加权平均价,销量多的价格权重更高。

4. 四舍五入与空值处理

  • ROUND(..., 2):保留两位小数
  • IFNULL(..., 0):如果没有销售记录,结果为 NULL,替换为 0

❓ 常见疑问解答

Q1:ON 后面那句 AND ... BETWEEN ... AND ... 是什么意思?

AND UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date
  • 这是一个日期范围匹配条件,确保销售日期落在价格的有效期内。
  • 等价于:
    AND UnitsSold.purchase_date >= Prices.start_date
    AND UnitsSold.purchase_date <= Prices.end_date

Q2:SUM(Prices.price * UnitsSold.units) / SUM(UnitsSold.units) 怎么理解?

  • 分子:总销售额(每笔销售的价格 × 数量之和)
  • 分母:总销售数量
  • 结果:加权平均售价,销量多的价格影响更大。

总结一句话

这段 SQL 的作用是:计算每个产品在其价格生效期间内的实际加权平均售价,即使没有销售记录也要显示,价格为 0。

posted @ 2025-11-05 11:26  gccbuaa  阅读(11)  评论(0)    收藏  举报