max()查单列最大值时自动忽略null,全列为null则返回null;字符串按字典序比较;需配合select使用,不可单独写;查整行需子查询或窗口函数;group by中非聚合字段结果不可靠;有合适索引时可仅扫描索引最右节点。

直接用 MAX() 查单列最大值,但要注意 NULL
MAX() 会自动忽略 NULL 值,只在非空值中找最大。如果整列都是 NULL,结果就是 NULL,不是报错——这点常被误以为“查不到数据”。
基础写法很简单:
SELECT MAX(<code>price</code>) FROM <code>products</code>;
- 必须配合
SELECT,不能单独写MAX(price) - 不加
WHERE就是全表扫描,大数据量时注意性能 - 若列是字符串类型(如
VARCHAR),MAX()按字典序比较,不是按长度或数值大小
查最大值所在行的完整记录,不能只靠 MAX()
MAX() 只返回值,不带其他字段。想拿到“价格最高那条商品的 id、name、price”,直接 SELECT id, name, MAX(price) 会报错(MySQL 5.7+ 默认 SQL mode 下)或返回不可靠结果。
- 正确做法是子查询或窗口函数:
SELECT * FROM <code>products</code> WHERE <code>price</code> = (SELECT MAX(<code>price</code>) FROM <code>products</code>);
- 如果有多个相同最大值,上面语句会返回全部——这是合理行为,不是 bug
- MySQL 8.0+ 可用
ROW_NUMBER() OVER (ORDER BY price DESC)限制取 1 行,但需注意并列情况
MAX() 在 GROUP BY 中的常见误用
想分组查每类商品的最高价,写成 SELECT category, MAX(price) FROM products GROUP BY category 是对的;但一旦加上没聚合也没分组的字段(比如 name),就容易出问题:
SELECT category, <code>name</code>, MAX(<code>price</code>) FROM <code>products</code> GROUP BY <code>category</code>; <!-- 错误!name 不确定来自哪行 -->
- MySQL 允许这种写法(取决于 sql_mode),但
name值是随机选取的,不可预测 - PostgreSQL / SQL Server 直接报错:
column "name" must appear in the GROUP BY clause or be used in an aggregate function - 真要带对应名称,得用子查询、
JOIN或窗口函数(如FIRST_VALUE(name) OVER (PARTITION BY category ORDER BY price DESC))
性能和索引:MAX() 走不走索引?
多数主流数据库(MySQL InnoDB、PostgreSQL、SQL Server)在有合适索引时,MAX() 可以只查索引 B+ 树最右叶子节点,不用扫全表。
- 前提:查询列上有单列索引或复合索引的最左前缀,例如
INDEX(price) - 如果写成
MAX(price + 1)或MAX(ABS(price)),索引失效,变成全索引扫描甚至全表扫描 - 执行计划里看到
type: index或Extra: Using index才算走了覆盖索引 - 注意:
WHERE条件会改变索引使用逻辑,比如SELECT MAX(price) FROM products WHERE status = 'on_sale',需要的是(status, price)复合索引
别忘了检查执行计划,也别默认 MAX() 就一定快——它快的前提是索引设计匹配查询模式。











