Fel*_*ffa 4 sql snowflake-cloud-data-platform
我正在尝试在 Snowflake 中使用GREATEST(),但每当我有空值时,我都会得到null而不是所需的结果:
select greatest(1,2,null);
-- null
Run Code Online (Sandbox Code Playgroud)
这种行为让很多人感到困惑,它始于 Oracle 中的行为GREATEST(),Snowflake 与之匹配:
Snowflake 论坛中也对此进行了讨论:
样本数据:
create or replace table some_nulls
as (
select $1 a, $2 b, $3 c
from values(1.1, 2.3, null::float), (null, 2, 3.5), (1, null, 3), (null, null, null)
);
select greatest(a, b)
from some_nulls;
Run Code Online (Sandbox Code Playgroud)
在此询问以获得最佳可用解决方案。
Luk*_*zda 10
GREATEST和LEASTwithIGNORE NULLS可以通过ARRAY_MIN和ARRAY_MAX函数来模拟:
SELECT GREATEST(1,2,NULL), LEAST(1,2,NULL),
ARRAY_MAX([1,2,NULL]), ARRAY_MIN([1,2,NULL]);
-- NULL NULL 2 1
Run Code Online (Sandbox Code Playgroud)
输出:
返回的输出具有VARIANT数据类型,应显式转换:ARRAY_MAX([...])::NUMBER。
| 功能 | 行为等同 |
|---|---|
| 最伟大的(...) | 最伟大的(...)尊重空值 |
| 至少(...) | 最少(...)尊重空值 |
| ARRAY_MAX(...) | 最伟大的(...)忽略空值 |
| ARRAY_MIN(...) | LEAST(...) 忽略空值 |
此方法也适用于列:
CREATE OR REPLACE TABLE tab(col1, col2, col3) AS
SELECT 1 ,2, NULL
UNION ALL SELECT 10, 20, 30;
SELECT *,
GREATEST(col1, col2, col3),
ARRAY_MAX([col1, col2, col3])::NUMBER
FROM tab;
Run Code Online (Sandbox Code Playgroud)
这些功能存在但默认情况下未启用:
SHOW FUNCTIONS LIKE 'ARRAY_M%';
ARRAY_MAX(ARRAY) RETURN VARIANT the maximum defined element in the array, or NULL
ARRAY_MIN(ARRAY) RETURN VARIANT the minimum defined element in the array, or NULL
Run Code Online (Sandbox Code Playgroud)
SELECT SYSTEM$ENABLE_BEHAVIOR_CHANGE_BUNDLE('2023_05');
Run Code Online (Sandbox Code Playgroud)
7.29 版本(8 月 22 日至 23 日)中状态更改为默认启用;帐户管理员可以禁用选择退出。
可以使用 ARRAY 处理可为空的列:
SELECT a,b,c, GREATEST([a],[b],[c])[0]::INT
FROM some_nulls;
Run Code Online (Sandbox Code Playgroud)
对于样本数据:
CREATE OR REPLACE TABLE some_nulls(a INT, b INT, c INT)
AS
SELECT 1, 2, NULL UNION
SELECT NULL, 2, 3 UNION
SELECT 1, NULL, 3 UNION
SELECT NULL, NULL, NULL;
Run Code Online (Sandbox Code Playgroud)
输出:
怎么运行的:
NULL成为[undefined]最低元素,因此这种方法可以用于GREATEST但不能用于LEAST函数。
编辑:根据丹尼斯的评论:-(GREATEST( [-a] ,[-b], [-c] )[0]::INT)发现LEAST价值
编辑:最近引入的 ARRAY_MIN/MAX 函数可以实现更简洁的方法:/sf/answers/5368295691/