特定产品ID的各门店价格查询:SQL语句错误排查与修正
问题分析与解决方案
原SQL的核心问题
你的查询出现两个异常:所有行的product_price和price_updated完全重复,还带出了未售卖该产品的门店,根源在于缺少products与products_prices的关联条件,导致产生笛卡尔积,同时排序方向不符合需求:
- 未指定
products_prices和products的关联规则(ON pr.id = pp.id_product),导致所有门店记录都强制匹配pp.id_product = '30'的那条价格数据,因此所有行的价格/更新时间完全一致,还拉取了无关门店。 - GROUP BY的逻辑冗余且错误:你不需要按价格和更新时间分组,反而会拆分正常的门店记录。
- 排序方向与期望相反:原SQL用了价格降序,而你需要价格升序、更新时间降序。
修正后的SQL
如果你的需求是获取所有售卖“ICA Basic Milk & Caramel”产品的门店价格(匹配你给出的期望结果),可以使用以下查询:
SELECT pl.id AS place_id, pl.data_name AS place_name, pp.data_price AS product_price, pp.date_updated AS price_updated FROM places AS pl INNER JOIN products AS pr ON pl.id = pr.id_place INNER JOIN products_prices AS pp ON pr.id = pp.id_product WHERE pr.data_name = 'ICA Basic Milk & Caramel' ORDER BY pp.data_price ASC, pp.date_updated DESC;
如果确实需要严格按**产品ID(products.id = 30)**查询,那只会返回门店26的记录,只需调整WHERE条件:
WHERE pr.id = 30
进阶:处理同一门店多价格记录
如果某个门店对该产品有多个历史价格记录,想要获取每个门店的最新价格,可以使用窗口函数ROW_NUMBER()实现:
SELECT place_id, place_name, product_price, price_updated FROM ( SELECT pl.id AS place_id, pl.data_name AS place_name, pp.data_price AS product_price, pp.date_updated AS price_updated, -- 按门店分组,标记出更新时间最晚的价格记录 ROW_NUMBER() OVER (PARTITION BY pl.id ORDER BY pp.date_updated DESC) AS rn FROM places AS pl INNER JOIN products AS pr ON pl.id = pr.id_place INNER JOIN products_prices AS pp ON pr.id = pp.id_product WHERE pr.data_name = 'ICA Basic Milk & Caramel' ) AS price_subquery WHERE rn = 1 ORDER BY product_price ASC, price_updated DESC;
为什么这样有效?
INNER JOIN确保只返回同时存在于三个表中的记录,自动过滤掉未售卖该产品的门店。- 明确的
ON关联条件避免了笛卡尔积,保证价格数据和对应门店正确匹配。 - 调整后的
ORDER BY完全符合你“价格从低到高、更新时间从新到旧”的排序需求。
内容的提问来源于stack exchange,提问作者user718990
相关产品推荐
相关产品推荐

