SQL Server 2022 首次原生支持 GREATEST 函数,用于单行多列取最大值,跳过 NULL 但要求参数类型兼容;非 2022 版本报错,且不可替代跨行聚合 MAX()。

GREATEST 在 SQL Server 2022 中已原生支持,可直接用于取单行内多个列/表达式的最大值,无需绕路写 CASE WHEN 或 UNION ALL。但它不是聚合函数,不能替代跨行的 MAX();用错场景会导致结果完全不符预期。
确认你的 SQL Server 版本是否真支持 GREATEST
SQL Server 2022(含 Azure SQL Database)是首个支持 GREATEST 的 Microsoft 官方版本。低于此版本(如 2019、2017)执行会报错:Invalid function name 'GREATEST'。验证方式:
SELECT SERVERPROPERTY('ProductVersion') AS Version;返回值以 16. 开头(如 16.0.4041.2)即为 2022;若为 15.(2019)或更低,则该函数不可用。
GREATEST(col1, col2, col3) 的 NULL 行为与隐式转换规则
它跳过 NULL 值比较,但只要**任一参数为 NULL 且其余全为 NULL**,就返回 NULL;若其余有非 NULL 值,则正常返回其中最大者。关键点在于类型兼容性:
-
GREATEST(10, NULL, 8)→ 返回10(跳过 NULL,比较 10 和 8) -
GREATEST(NULL, NULL)→ 返回NULL -
GREATEST(10, '20')→ 先隐式转成同类型:数值优先级高,'20'转为INT成功,结果为20 -
GREATEST(10, 'abc')→ 转换失败,报错:Conversion failed when converting the varchar value 'abc' to data type int. - 混合字符串时按字典序比:
GREATEST('apple', 'banana')→'banana'('b'>'a')
替代方案:当字段可能为 NULL 且业务不允许丢值时
直接用 GREATEST 遇到 NULL 就“消失”,但有时你需要把 NULL 当作极小值(如价格字段)或极大值(如截止日期)参与比较。这时必须预处理:
- 把 NULL 视为 0(仅适用于非负数值):
GREATEST(ISNULL(col1, 0), ISNULL(col2, 0)) - 更安全(避免 0 干扰):
GREATEST(ISNULL(col1, -999999.99), ISNULL(col2, -999999.99)) - 字符串字段补空串:
GREATEST(ISNULL(name_a, ''), ISNULL(name_b, '')) - 若需保留原始 NULL 意义(比如“未知”不应参与比较),则仍用
CASE WHEN显式控制逻辑,GREATEST不适合该场景
和 MAX() / OVER() 混用的常见误解
GREATEST 是标量函数,作用域仅限当前行;它不能和 GROUP BY 或 OVER() 直接组合来“跨行取最大”。下面写法是错的:
SELECT id, GREATEST(a, b, c) AS row_max FROM t GROUP BY id; -- ✅ 合法,但只是每行算一次<br>SELECT id, MAX(GREATEST(a, b, c)) OVER() AS global_max FROM t; -- ✅ 合法,先算每行最大,再对结果取全局 MAX<br>SELECT id, GREATEST(MAX(a), MAX(b), MAX(c)) FROM t GROUP BY id; -- ❌ 报错:聚合函数不能嵌套在 GREATEST 内
真正容易被忽略的是:你往往需要的不是“每行三列谁最大”,而是“这三列各自的最大值”——那应该写三遍 MAX(),而不是一遍 GREATEST。

















