本文目录
显示
📌 概述
GREATEST 和 LEAST 是 SQL Server 2022(16.x)及以后版本引入的两个逻辑函数,用于在多个表达式中找出最大值和最小值。这两个函数使 SQL 代码更加简洁,无需使用复杂的 CASE 语句即可实现多值比较。
| 函数 | 功能 | 支持版本 |
|---|---|---|
| GREATEST | 返回参数列表中的最大值 | SQL Server 2022+ |
| LEAST | 返回参数列表中的最小值 | SQL Server 2022+ |
⚠️ 注意:这两个函数仅适用于 SQL Server 2022 及更高版本、Azure SQL 数据库、Azure SQL Managed Instance、Azure Synapse Analytics 等平台。
📝 语法
GREATEST 函数语法
GREATEST(表达式1, 表达式2, ..., 表达式N)
LEAST 函数语法
LEAST(表达式1, 表达式2, ..., 表达式N)
参数说明:
- 表达式1, 表达式2, …, 表达式N:任何可比较数据类型的逗号分隔表达式列表(可以是常量、列名或表达式)
- 至少需要两个参数
- 所有参数的数据类型必须兼容(可隐式转换为同一类型)
💡 实例演示
以下示例均使用中文字段名和表名,便于理解。
示例1:比较数字常量
-- 找出最大值
SELECT GREATEST(10, 3, 15, 7) AS 最大值; -- 结果:15
-- 找出最小值
SELECT LEAST(10, 3, 15, 7) AS 最小值; -- 结果:3
示例2:比较表中的列值
假设有一个名为 员工信息 的表:
| 员工编号 | 姓名 | 基本工资 | 绩效奖金 | 补贴 |
|---|---|---|---|---|
| 001 | 张三 | 5000 | 2000 | 1000 |
| 002 | 李四 | 6000 | 1500 | 800 |
| 003 | 王五 | 4500 | 2500 | 1200 |
-- 找出每位员工各项收入中的最高值
SELECT
姓名,
基本工资,
绩效奖金,
补贴,
GREATEST(基本工资, 绩效奖金, 补贴) AS 最高收入项
FROM 员工信息;
结果:
| 姓名 | 基本工资 | 绩效奖金 | 补贴 | 最高收入项 |
|---|---|---|---|---|
| 张三 | 5000 | 2000 | 1000 | 5000 |
| 李四 | 6000 | 1500 | 800 | 6000 |
| 王五 | 4500 | 2500 | 1200 | 4500 |
-- 找出每位员工各项收入中的最低值
SELECT
姓名,
基本工资,
绩效奖金,
补贴,
LEAST(基本工资, 绩效奖金, 补贴) AS 最低收入项
FROM 员工信息;
结果:
| 姓名 | 基本工资 | 绩效奖金 | 补贴 | 最低收入项 |
|---|---|---|---|---|
| 张三 | 5000 | 2000 | 1000 | 1000 |
| 李四 | 6000 | 1500 | 800 | 800 |
| 王五 | 4500 | 2500 | 1200 | 1200 |
示例3:日期比较
假设有一个 项目进度 表:
SELECT
项目名称,
计划开始日期,
实际开始日期,
GREATEST(计划开始日期, 实际开始日期) AS 最晚开始日期,
LEAST(计划开始日期, 实际开始日期) AS 最早开始日期
FROM 项目进度;
示例4:与 CASE 语句对比
传统写法(SQL Server 2022 之前):
SELECT
姓名,
CASE
WHEN 基本工资 >= 绩效奖金 AND 基本工资 >= 补贴 THEN 基本工资
WHEN 绩效奖金 >= 基本工资 AND 绩效奖金 >= 补贴 THEN 绩效奖金
ELSE 补贴
END AS 最高收入项
FROM 员工信息;
新写法(SQL Server 2022+):
SELECT
姓名,
GREATEST(基本工资, 绩效奖金, 补贴) AS 最高收入项
FROM 员工信息;
✅ 新写法代码量减少约 70%,可读性显著提升!
⚠️ 注意事项
1. NULL 值处理(最重要!)
如果任何参数为 NULL,GREATEST 和 LEAST 函数将返回 NULL。
-- 以下查询将返回 NULL
SELECT GREATEST(10, NULL, 15) AS 结果; -- 结果:NULL
SELECT LEAST(10, NULL, 15) AS 结果; -- 结果:NULL
解决方案:使用 COALESCE 或 ISNULL 函数预处理 NULL 值
-- 方法1:使用 COALESCE(推荐,标准 SQL)
SELECT
姓名,
GREATEST(
COALESCE(基本工资, 0),
COALESCE(绩效奖金, 0),
COALESCE(补贴, 0)
) AS 最高收入项
FROM 员工信息;
-- 方法2:使用 ISNULL(SQL Server 特有)
SELECT
姓名,
GREATEST(
ISNULL(基本工资, 0),
ISNULL(绩效奖金, 0),
ISNULL(补贴, 0)
) AS 最高收入项
FROM 员工信息;
2. 数据类型兼容性
所有参数必须是可比较的数据类型,或可隐式转换为同一类型。
-- ✅ 正确:都是数字类型
SELECT GREATEST(10, 20, 30);
-- ✅ 正确:都是日期类型
SELECT GREATEST('2024-01-01', '2024-06-01', '2024-03-01');
-- ❌ 错误:类型不兼容
SELECT GREATEST(10, '2024-01-01'); -- 会报错
3. 版本兼容性
| SQL Server 版本 | GREATEST/LEAST 支持 |
|---|---|
| SQL Server 2019 及更早 | ❌ 不支持 |
| SQL Server 2022+ | ✅ 支持 |
| Azure SQL 数据库 | ✅ 支持 |
| Azure Synapse Analytics | ✅ 支持 |
如果您的数据库版本低于 2022,需要使用 CASE 语句替代:
-- GREATEST 的替代写法(兼容旧版本)
SELECT
CASE
WHEN 列1 >= 列2 AND 列1 >= 列3 THEN 列1
WHEN 列2 >= 列1 AND 列2 >= 列3 THEN 列2
ELSE 列3
END AS 最大值
FROM 表名;
-- LEAST 的替代写法(兼容旧版本)
SELECT
CASE
WHEN 列1 <= 列2 AND 列1 <= 列3 THEN 列1
WHEN 列2 <= 列1 AND 列2 <= 列3 THEN 列2
ELSE 列3
END AS 最小值
FROM 表名;
4. 参数数量限制
- 至少需要 2 个参数
- 理论上没有上限,但建议不超过 10-15 个参数以保持代码可读性
-- ❌ 错误:只有一个参数
SELECT GREATEST(10); -- 会报错
-- ✅ 正确:至少两个参数
SELECT GREATEST(10, 20);
5. 与聚合函数 MAX/MIN 的区别
| 特性 | GREATEST/LEAST | MAX/MIN |
|---|---|---|
| 类型 | 标量函数 | 聚合函数 |
| 作用范围 | 比较同一行的多个列/表达式 | 比较多行的单个列 |
| 示例 | GREATEST(列1, 列2, 列3) | MAX(列1) |
-- GREATEST:比较同一行的多个列
SELECT GREATEST(基本工资, 绩效奖金) FROM 员工信息;
-- MAX:比较多行的单个列
SELECT MAX(基本工资) FROM 员工信息;
🔧 实用应用场景
场景1:价格区间限制
-- 确保价格在最低和最高限制之间
SELECT
商品名称,
原价,
GREATEST(原价, 最低限价) AS 调整后价格,
LEAST(GREATEST(原价, 最低限价), 最高限价) AS 最终价格
FROM 商品表;
场景2:计算有效期
-- 取多个截止日期中最晚的一个
SELECT
订单编号,
GREATEST(订单日期, 付款日期, 发货日期) AS 最晚业务日期
FROM 订单表;
场景3:数据质量检查
-- 找出异常数据(某列值小于其他列)
SELECT *
FROM 成绩表
WHERE LEAST(语文成绩, 数学成绩, 英语成绩) < 0;
📊 性能建议
- 索引优化:GREATEST/LEAST 函数本身无法利用索引,但可以在 WHERE 子句的条件列上创建索引
- 避免在 WHERE 子句中对列使用函数:这可能导致索引失效
- NULL 预处理:如果表中 NULL 值较多,建议使用 COALESCE 预处理
✅ 总结
| 要点 | 说明 |
|---|---|
| 引入版本 | SQL Server 2022+ |
| 核心功能 | 多值比较,返回最大/最小值 |
| NULL 处理 | 任一参数为 NULL 则返回 NULL,需用 COALESCE 预处理 |
| 数据类型 | 所有参数必须类型兼容 |
| 替代方案 | 旧版本使用 CASE 语句 |
| 与 MAX/MIN 区别 | GREATEST/LEAST 是标量函数,MAX/MIN 是聚合函数 |
掌握这两个函数可以让您的 SQL 代码更加简洁、可读性更强,特别适合需要进行多列比较的场景!


请登录后查看回复内容