MIN() OVER 必须搭配 PARTITION BY 才能按类别计算最低价,否则返回全表最小值;要获取最低价对应完整记录需结合 ROW_NUMBER() 或子查询等方法。

MIN() OVER 需搭配 PARTITION BY 才能按类别分组计算
直接写 MIN(price) OVER() 会返回全表最低价,不是每个类别的最低价。关键在于必须用 PARTITION BY category 明确划分窗口范围。
常见错误是漏掉 PARTITION BY,结果所有行都显示同一个最小值,看起来“没生效”。
- 正确写法:
MIN(price) OVER (PARTITION BY category) - 错误写法:
MIN(price) OVER ()(无分区,全局最小) - 如果还想要排序(比如取最低价那条记录),
ORDER BY放在窗口定义里会影响累积行为,这里不需要
想查出“价格最低的那条产品记录”,不能只靠 MIN() OVER
MIN() OVER 只能算出每个类别的最低价格数值,但无法定位到是哪一行。要拿到完整产品信息(比如 product_name),得配合其他手段。
- 方案一:用
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price)标记每类中价格最低的行(rn = 1),再过滤 - 方案二:用
WHERE (category, price) IN (SELECT category, MIN(price) FROM products GROUP BY category),注意多列 IN 在部分数据库(如旧版 MySQL)不支持 - 方案三:用关联子查询,但性能通常较差,尤其数据量大时
不同数据库对 NULL 的处理可能影响结果
MIN() 默认忽略 NULL 值,但如果某类所有 price 都是 NULL,对应窗口结果就是 NULL,而不是报错或跳过。
- PostgreSQL、SQL Server、Oracle 行为一致:跳过
NULL,无非空值则结果为NULL - 如果业务上
price IS NULL表示“未定价”,而你希望这类别不参与比较,得提前WHERE price IS NOT NULL - 别指望
MIN() OVER自动过滤掉整行 —— 它只影响聚合值,原行照常输出
性能敏感时,注意窗口函数和索引的配合
虽然 PARTITION BY category ORDER BY price 理论上能走索引,但多数数据库对窗口函数的索引利用有限,尤其是只建了 (category) 单列索引时。
- 较优索引:复合索引
(category, price),可加速分区 + 排序过程 - 如果只是算
MIN(price) OVER (PARTITION BY category)(无ORDER BY),部分引擎(如 PostgreSQL 14+)能用到(category, price)索引优化聚合 - 别在大表上随意加
ORDER BY price到窗口定义里 —— 即使你没显式排序,也容易触发临时排序操作
MIN() OVER (PARTITION BY category) 算出每类最低价,再用这列和原始 price 比较是否相等;但要注意并列最低价时会返回多行——这点很容易被忽略。

















