GROUP BY配合MIN()用于查每组最低价格,必须同时在SELECT和GROUP BY中包含分组字段;WHERE过滤行,HAVING过滤分组;NULL值使MIN()返回NULL;索引可优化性能,但ORDER BY可能破坏优化;返回完整记录需用窗口函数或子查询。

GROUP BY配合MIN()查每组最低价格
直接在SELECT里用MIN(price)必须搭配GROUP BY,否则会报错或返回全表最小值而非分组结果。常见错误是漏写GROUP BY,导致结果不符合预期。
典型场景:按商品类别找最低售价,或按供应商查最低报价。
- 必须把分组字段(如
category、supplier_id)同时写进SELECT和GROUP BY - 不能在
SELECT中混用非分组字段和聚合函数(比如SELECT category, name, MIN(price)会出错) - 若还需查出对应最低价的整条记录(比如哪个SKU),
MIN()本身做不到,得换用窗口函数或子查询
SELECT category, MIN(price) AS min_price FROM products GROUP BY category;
WHERE和HAVING的区别影响结果筛选
WHERE过滤行,HAVING过滤分组——这是决定“先筛再分组”还是“先分组再筛”的关键。
例如:只想看平均价>100的品类中,哪个品类的最低价最低?必须用HAVING先限制分组范围,再算MIN()。
-
WHERE price > 0:排除脏数据,作用于原始行 -
HAVING COUNT(*) > 5:只保留商品数超5个的品类,作用于分组后 - 误把条件写进
WHERE可能提前剔除本该参与分组的记录,导致MIN()结果偏高
SELECT category, MIN(price) FROM products WHERE price IS NOT NULL GROUP BY category HAVING AVG(price) > 100;
NULL值会让MIN()返回NULL,不是忽略它
MIN()默认跳过NULL,但如果某组所有price都是NULL,结果就是NULL——这点容易被当成“没数据”,实际可能是数据质量问题。
- 检查是否有整组
price全为NULL:SELECT category FROM products GROUP BY category HAVING COUNT(price) = 0 - 想把
NULL当0处理?不行,MIN()不接受COALESCE(price, 0)作为参数(语法错误),得先用COALESCE生成临时列再聚合 - 某些数据库(如PostgreSQL)支持
MIN(price) FILTER (WHERE price IS NOT NULL),但MySQL不支持
SELECT category, MIN(COALESCE(price, 999999)) AS min_price FROM products GROUP BY category;
性能注意:索引对MIN()是否生效取决于写法
如果只查MIN(price)且GROUP BY字段有索引,优化器可能走索引快速定位每组极值,不用全表扫描。但加了ORDER BY或LIMIT反而可能破坏这个优化。
- 高效写法:
SELECT category, MIN(price) FROM products GROUP BY category(假设(category, price)有联合索引) - 低效陷阱:
SELECT category, MIN(price) FROM products GROUP BY category ORDER BY MIN(price)——排序迫使临时表物化,失去索引优势 - MySQL 8.0+ 支持函数索引,可建
INDEX ON products (category, price)提升速度;旧版本建议用覆盖索引
真正麻烦的是要返回最低价那条完整记录时,MIN()完全帮不上忙——这时候得用ROW_NUMBER() OVER (PARTITION BY category ORDER BY price)或者相关子查询,逻辑和性能都更重。

















