如何在带有空值的 Snowflake 中使用“GREATEST()”?

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

GREATESTLEASTwithIGNORE NULLS可以通过ARRAY_MINARRAY_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)

2023_05 套装

SELECT SYSTEM$ENABLE_BEHAVIOR_CHANGE_BUNDLE('2023_05');
Run Code Online (Sandbox Code Playgroud)

7.29 版本(8 月 22 日至 23 日)中状态更改为默认启用;帐户管理员可以禁用选择退出。

  • 这确实是一个很好的解决方法 (2认同)

Luk*_*zda 8

可以使用 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/

  • 这很有趣,我喜欢它。只是为了表明它不需要强制转换为 int,float 也可以工作:`SELECT a,b,c, GREATEST([a],[b],[c])[0]::float FROM some_nulls;` (2认同)