least和greatest在mysql/postgresql中用于逐行比较多列取最小或最大非null值,不支持sql server和sqlite原生;需注意类型兼容、null跳过但全null返回null,不可替代跨行聚合的min/max。

LEAST 和 GREATEST 在 MySQL/PostgreSQL 中怎么用?
这两个函数在 MySQL 和 PostgreSQL 中原生支持,用于从多个表达式中直接取最小值或最大值,**不支持 SQL Server 或 SQLite(原生)**。它们不是聚合函数,不配合 GROUP BY 使用,而是逐行计算——这点常被误当成 MIN() 或 MAX() 的替代品。
常见错误是写成 SELECT LEAST(col1, col2, col3) FROM t GROUP BY id 却期待它返回全表极值,实际只是每行三列比大小。
-
LEAST(a, b, c)返回 a、b、c 中最小的非 NULL 值;若全部为 NULL,则返回 NULL -
GREATEST(a, b, c)同理,返回最大非 NULL 值 - 所有参数必须类型兼容(如不能混用字符串和日期),否则报错:
Operand should contain 1 column(s)或隐式转换失败 - MySQL 8.0+ 和 PostgreSQL 支持任意数量参数;旧版 MySQL(5.7)最多支持 2 个参数
为什么不能直接替代 MIN()/MAX() 聚合?
因为 LEAST 作用于「单行内多个字段」,而 MIN(col) 作用于「单列跨多行」。想取某列的全局最小值,仍得用 MIN();想取每行中 price、discount_price、sale_price 里最低的那个价,才轮到 LEAST()。
典型场景:电商商品表有 list_price、promo_price、member_price 三列,要算“用户实际可见的最低价”:
SELECT id, LEAST(list_price, promo_price, member_price) AS final_price FROM products;
如果其中一列为 NULL(比如没促销价),LEAST 自动跳过它——但要注意,LEAST(100, NULL, 80) 结果是 80,不是 NULL。
NULL 值处理和类型转换陷阱
这是最容易翻车的地方。两个关键行为必须记牢:
-
LEAST(10, '5', 3.2)在 MySQL 中会把字符串转成数字比较,结果是 3.2;但在 PostgreSQL 中会报错:ERROR: argument of LEAST must be same type -
LEAST(NULL, NULL, 10)返回 10;但LEAST(NULL, NULL)返回 NULL —— 没有非 NULL 候选值时无解 - 如果字段含空字符串
'',MySQL 会把它转成 0(数值上下文),可能意外压低结果;建议提前用NULLIF(col, '')清洗
安全写法示例(防 NULL + 类型对齐):
SELECT LEAST( COALESCE(price, 999999), COALESCE(discount_price, 999999), COALESCE(member_price, 999999) ) AS min_offered FROM products;
SQL Server 和 SQLite 用户怎么办?
它们不支持 LEAST/GREATEST,但可以用 CASE 模拟,不过列数一多就爆炸。3 列还能忍:
SELECT CASE WHEN a <p>更现实的方案是:升级到支持该语法的数据库,或改用应用层计算(比如 Python 的 <code>min(row['a'], row['b'], row['c'])</code>)。硬写 5 列的嵌套 <code>CASE</code> 不仅难维护,执行计划也容易变差。</p> <p>真正容易被忽略的是跨数据库迁移时的语法断点——开发在 MySQL 上用得飞起的 <code>LEAST</code>,上线到 SQL Server 就直接报错,连 warning 都没有。</p>











