mysql如何使用MAX/MIN获取极值_mysql最大值与最小值查找

2次阅读

max()和min()忽略NULL,整列null时返回null;查整行需子查询或order by+limit;where过滤优于having;无索引时全表扫描,性能差。

mysql如何使用MAX/MIN获取极值_mysql最大值与最小值查找

MAX()MIN() 查单列极值,但别忘了 NULL 会自动被忽略

这两个函数只对非 NULL 值计算,如果整列都是 NULL,结果就是 NULL。常见误判是看到返回 NULL 就以为没数据,其实可能是数据本身为空或类型不匹配(比如字符串字段存了空串 '',它不等于 NULL,但 MIN() 仍会参与比较)。

  • 数值型字段放心用:select MAX(price), MIN(price) FROM products;
  • 字符串按字典序比:MIN(name) 返回字母最靠前的值,不是长度最短的
  • 日期字段也适用:MAX(created_at) 得到最后时间,前提是字段是 dateTIMEDATE 类型,别用 VARCHAR 存时间

查带条件的极值,WHEREHAVING 更安全

HAVING 是分组后的过滤,容易在没 GROUP BY 时出错或逻辑绕弯。要查“2023 年销量最高的商品”,直接用 WHERE 先筛年份,再套 MAX(),而不是先聚合再过滤。

  • ✅ 正确:SELECT MAX(sales) FROM orders WHERE YEAR(order_date) = 2023;
  • ❌ 危险:SELECT MAX(sales) FROM orders HAVING YEAR(order_date) = 2023; —— 这句语法可能通过,但语义错误,HAVING 无法引用未聚合的 order_date
  • 注意:如果条件涉及聚合结果(如“平均单价 > 100 的品类中找最高价”),才需要 HAVING 配合 GROUP BY

想查整行记录(比如价格最高的那条商品),MAX() 不能直接返回其他字段

MAX(price) 只返回价格数值,不会顺带把对应商品的 nameid 一起捞出来。这是初学者最常卡住的地方——以为加个 SELECT id, name, MAX(price) 就能拿到完整记录,实际会报错或返回不可预测的 id(取决于 sql 模式,比如 ONLY_FULL_GROUP_BY 开启时直接拒绝执行)。

  • ✅ 推荐做法:用子查询定位极值,再关联原表
    SELECT * FROM products WHERE price = (SELECT MAX(price) FROM products);
  • ✅ 替代方案:用 ORDER BY ... LIMIT 1(注意有并列最高值时只取一条)
    SELECT * FROM products ORDER BY price DESC LIMIT 1;
  • ⚠️ 避免:SELECT id, name, MAX(price) FROM products; —— 在严格模式下会失败,在宽松模式下 idname 值无业务意义

性能要注意:极值查询没索引时会全表扫描

MAX()MIN() 在有对应索引的字段上可以走索引 B+ 树的最左/最右叶子节点,几乎 O(1);但如果没有索引,就得扫完整张表。尤其当表有千万级数据、又频繁查最新时间或最高金额时,慢得明显。

  • 检查是否命中索引:EXPLAIN SELECT MAX(updated_at) FROM logs;type 是否为 indexrange
  • 复合索引要注意顺序:如果常用 WHERE status = 1 ORDER BY created_at DESC 再取极值,建索引优先考虑 (status, created_at),而不是反过来
  • MIN(id) 在主键上天然快,但 MIN(non_indexed_column) 就是硬扫

事情说清了就结束。极值本身简单,难的是搞清它和上下文的关系——在哪过滤、怎么取整行、有没有索引兜底。这几个点漏一个,线上就容易卡住或返回错数据。

text=ZqhQzanResources