平均售价:按销售日期匹配当时的价格
LeetCode 1251 · 区间关联(日期落在价格有效期内)、加权平均
面试怎么回答
销量表和价格表按 product_id 关联,并且 purchase_date BETWEEN start_date AND end_date,确保用的是销售当天的价格;然后按产品 SUM(price * units) / SUM(units) 求加权平均。这种「事实按日期落到维度有效区间」的关联,和数仓里拉链表的用法完全一样。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
价格表记录每个产品在一段时间内的单价(时间段不重叠),销量表记录每次销售的日期和数量。求每个产品的平均售价 = 总销售额 / 总销量,保留两位小数。
表结构
- Prices:product_id、start_date、end_date、price;(product_id, start_date, end_date) 为主键
- UnitsSold:product_id、purchase_date、units;可能有重复行
思路
每笔销售要用销售当天生效的价格,所以关联条件除了产品 ID 相同,还要「销售日期在价格的起止日期之间」,这是一种区间关联(和拉链表按日期关联维度是同一回事)。关联后按产品算 SUM(price * units) / SUM(units),这是按销量加权的平均价,不是价格的简单平均。
参考解法
SELECT
product_id,
Round(SUM(sales) / SUM(units), 2) AS average_price
FROM (
SELECT
Prices.product_id AS product_id,
Prices.price * UnitsSold.units AS sales,
UnitsSold.units AS units
FROM Prices
JOIN UnitsSold ON Prices.product_id = UnitsSold.product_id
WHERE UnitsSold.purchase_date BETWEEN Prices.start_date AND Prices.end_date
) T
GROUP BY product_id
易错点
- 用 AVG(price) 得到的是价格的简单平均,没有按销量加权。
- 只按产品 ID 关联不加日期条件,一笔销售会匹配到所有价格段。
- 如果要求没卖出的产品显示 0,需要以价格表为主表 LEFT JOIN,并处理除以 0。