min()需配合group by才能查每组最低价,单独使用只返回全局最小值;漏写group by或select非聚合字段会报错;查最低价商品完整信息须用窗口函数或子查询;索引顺序影响group by性能;min()自动忽略null,全null组返回null。

MIN() 配合 GROUP BY 才能查每组最低价格
单独用 MIN(price) 只会返回整张表的全局最小值,不是每组的。必须搭配 GROUP BY 指定分组维度,比如按 category 或 product_type 分组。
常见错误是漏写 GROUP BY,或者把非聚合字段(如 product_name)直接放进 SELECT 列表里却没包含在 GROUP BY 中——这在 MySQL 5.7+ 严格模式或 PostgreSQL、SQL Server 下会报错:ERROR: column "product_name" must appear in the GROUP BY clause。
- 正确写法:先明确你要按什么字段分组,例如
SELECT category, MIN(price) FROM products GROUP BY category - 如果还想查出对应最低价格的商品名,不能直接加
product_name—— 因为一组可能有多个商品,MIN()不携带行上下文 - 此时需改用窗口函数(见下节)或子查询/JOIN 方式关联原始行
要查“哪件商品价格最低”,不能只靠 MIN()
MIN(price) 只返回数值,不告诉你这个价格属于哪一行。想拿到完整记录(比如最低价商品的 product_name、id),得绕开单纯聚合。
推荐用窗口函数,兼容性好且逻辑清晰:
SELECT product_name, category, price
FROM (
SELECT product_name, category, price,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price ASC) AS rn
FROM products
) ranked
WHERE rn = 1;
注意:ROW_NUMBER() 在价格相同时会任意排序;若需保留所有并列最低项,换成 RANK() 或 DENSE_RANK()。
- MySQL 8.0+、PostgreSQL、SQL Server、Oracle 都支持该写法
- SQLite 3.25+ 也支持窗口函数;老版本 SQLite 或 MySQL 5.6 需用自连接或相关子查询,性能较差
- 别用
ORDER BY price LIMIT 1套在子查询里——它只能返回单条全局记录,无法按组生效
GROUP BY 字段顺序和索引影响性能
当数据量大时,GROUP BY category, brand 的执行效率高度依赖联合索引是否覆盖这些字段及 price。
- 理想索引:
CREATE INDEX idx_cat_brand_price ON products(category, brand, price) - 如果只建了
(category)索引,MySQL 可能仍需临时表排序,慢在Using temporary; Using filesort - PostgreSQL 对索引顺序更敏感:前导字段必须完全匹配
GROUP BY列顺序才能高效利用索引 - 避免在
GROUP BY中用函数或表达式,如GROUP BY UPPER(category),会导致索引失效
NULL 值会被 MIN() 自动忽略,但要注意语义
MIN(price) 默认跳过 NULL,返回该组中非空最小值。这通常符合预期,但容易被忽略两点:
- 如果某组所有
price都是NULL,MIN()返回NULL,不是 0 或其他默认值 - 若业务要求把
NULL当作“无限高价格”参与比较(即取最小值时优先选非 NULL),需显式处理:MIN(COALESCE(price, 999999)) - 某些场景下,
NULL表示“未定价”,你可能需要先过滤:WHERE price IS NOT NULL再聚合











