GREATEST / LEAST 是什么
GREATEST 与 LEAST 是在同一行的多个表达式之间比较,返回其中最大或最小的那个值,属于「行内比较」而非跨行聚合。它们和 MAX / MIN 聚合函数完全不是一件事:GREATEST 看的是同一行里的几列,MAX 看的是同一列的多行。MySQL 8.0、PostgreSQL、Oracle 都提供这两个函数,SQL Server 没有同名函数,需要用 CASE 或子查询模拟。最容易踩的差异在 NULL 上:MySQL 只要任一参数为 NULL,结果就是 NULL;PostgreSQL 会忽略 NULL 参数,只有全部参数都是 NULL 才返回 NULL。
基本信息
| 适用平台 | MySQL 8.0 / PostgreSQL 11+ / Oracle;SQL Server 无同名函数 |
|---|---|
| 参数个数 | 至少两个,可以更多,全部参与比较 |
| 参数类型 | PostgreSQL 要求各参数类型一致或可隐式转换,否则直接报错,需显式 CAST |
| 返回值 | 与输入同类型;字符串按数据库排序规则比较 |
| NULL 规则 | MySQL:任一为 NULL 即返回 NULL;PostgreSQL / Oracle:忽略 NULL |
典型使用场景
- 同一行的多列取最值:两次考试成绩取高分、多来源报价取最低价
- 数值钳制:用 LEAST(x, 100) 限制上限、GREATEST(x, 0) 兜住下限,避免负数入库
- 时间比较:取 created_at 与 updated_at 中较晚的一个作为最后变更时间
- 阈值校验:LEAST(a, b, c) >= 60 判断多个指标是否同时达标
- 报表口径对齐:多个渠道上报同一指标时取最大值作为保守估计
基础用法
基础用法
SELECT id,
GREATEST(score_a, score_b) AS best_score, # 两列取较高分
LEAST(price, list_price, 999) AS final_price, # 价格上限钳制在 999
GREATEST(updated_at, created_at) AS last_change # 取较晚的时间
FROM products
WHERE status = 1; # 逐行计算,返回行数与源表一致与聚合函数的区别
与聚合函数的区别
SELECT GREATEST(a, b) FROM t; # 逐行比较两列,输出行数不变
SELECT MAX(v) FROM t; # 跨所有行取单列最大值,只输出一行
SELECT GREATEST(1, NULL); # MySQL: NULL,因为任一参数为 NULL
SELECT GREATEST(1, NULL); # PostgreSQL: 1,NULL 被忽略
SELECT GREATEST(NULL, NULL); # 两库都返回 NULL(全部为 NULL)平台行为对照
| 平台 | 参数含 NULL 时 | 备注 |
|---|---|---|
| MySQL 8.0 | 结果直接为 NULL | 需要兜底时在外面包 COALESCE |
| PostgreSQL | 忽略 NULL 参数 | 类型必须一致,1 与 '2' 混用会报错 |
| Oracle | 忽略 NULL 参数 | 字符型比较受 NLS 排序规则影响 |
| SQL Server | 无该函数 | 用 CASE 比较或 VALUES 派生表再取 MAX |
参数个数可以超过两个,全部参与比较;传入列名与字面量混用时要保证类型一致,PostgreSQL 下常见错误是 GREATEST(int_col, '5') 报类型不匹配。
不要用 GREATEST 判断「多列是否都非空」:PostgreSQL 忽略 NULL 的行为会让缺失值悄悄通过校验,判空要用 IS NULL 或 COALESCE 显式处理。