如果PostgreSQL数组的所有元素都为NULL,是否有表达式返回TRUE?
如果它是NULL以外的值,我当然可以使用类似的东西:
SELECT 4 = ALL (ARRAY[4,5]::integer[]);
但是我希望使用IS NULL
测试进行ALL操作,而不是= 4
测试。我不认为这有一个ALL语法,并且NULL周围的语义与数组复合我自己无法想到实现它的形式。因此我问Stack Overflow。 ; - )
我知道我可以在pl / sql或pl / pgsql中编写一个函数来执行此操作,但是我想在使用它之前看看是否有直接表达式。
答案 0 :(得分:8)
我认为我得到了最短的答案,同时仍保留4 = ALL (ARRAY[4,5]::integer[]);
构造:
实时测试:https://www.db-fiddle.com/f/6DuB1N4FdcvZdxKiHczu5y/1
select
y, true = ALL (select unnest(z) is null)
from x
答案 1 :(得分:8)
1 = ALL(arr) IS NULL AND 2 = ALL(arr) IS NULL
1
和2
可以任意两个不同的数字。
有两种方法。我组装了一个测试用例,看看哪个是最快的:
SELECT arr
, 1 = ALL(arr) IS NULL AND 2 = ALL(arr) IS NULL AS chk_simpl
, TRUE = ALL (SELECT unnest(arr) IS NULL) AS chk_michael
, (SELECT bool_and(e IS NULL) FROM unnest(arr) e) AS chk_bool_and
, NOT EXISTS (SELECT unnest(arr) EXCEPT SELECT null) AS chk_exist
FROM (
VALUES
('{[1,2,NULL,3}'::int[])
,('{1,1,1}')
,('{2,2,2}')
,('{NULL,NULL,NULL]}'::int[])
) t1(arr);
第二个来自currently accepted answer by @michael。 列按表达式的性能顺序排列。最快的。我建议的表达式实际上比其他表达快很多次。因此,我的答案。
SQL Fiddle with demo & performance test.
表达式1 = ALL(arr)
产生
TRUE
..如果所有元素都是1
FALSE
..如果任何元素是<> 1
(IS NOT NULL
)的任何元素
NULL
..如果至少有一个元素IS NULL
且没有元素是<> 1
因此,如果我们知道无法显示的单个元素,例如-1
,我们可以简化为:
-1 = ALL(arr) IS NULL
如果任何号码可以显示,请检查两个不同的号码。如果数组只包含NULL
,则结果只能为NULL
。瞧。
答案 2 :(得分:2)
我并不为此感到自豪,但是:
=> select not exists (
select 1
from (select all unnest(ARRAY[NULL, NULL, NULL]) is null as x) as dt
where x = 'f'
);
?column?
----------
t
(1 row)
=> select not exists (
select 1
from (select all unnest(ARRAY[NULL, 11, NULL]) is null as x) as dt
where x = 'f'
);
?column?
----------
f
(1 row)
是的,有很多子查询,但也许你可以使它工作或简化为可行的东西。
答案 3 :(得分:2)
另一种缩短代码的方法,使用每个聚合函数
create table x
(
y serial,
z int[]
);
insert into x(z) values(array[null,null,null]::int[])
insert into x(z) values(array[null,7,null]::int[])
insert into x(z) values(array[null,3,4]::int[])
insert into x(z) values(array[null,null,null,null]::int[])
with a as
(
select y, unnest(z) as b
from x
)
select y, every(b is null)
from a
group by y
order by y
输出:
y | every
---+-------
1 | t
2 | f
3 | f
4 | t
(4 rows)
另一种方法,生成用于比较的NULL:
select y,
z =
(select array_agg(null::int)
from generate_series(1, array_upper(z, 1) )) as IsAllNulls
from x
上面代码的基础逻辑,返回true:
SELECT ARRAY[NULL,NULL]::int[] = ARRAY[NULL,NULL]::int[]
另一种方法,使用array_fill
select y, z = array_fill(null::int, array[ array_upper(z, 1) ] )
from x
警告,数组构造和数组_fill不是对称的,测试这些:
select array[5]
-- array[5] here has different meaning from array[5] above
select array_fill(null::int, array[5])
答案 4 :(得分:1)
仅仅为了各种选择,我之前使用的是:
select array_remove(ARRAY[null::int, null, null], null) = '{}'
此方法对于数组中的任何值都将返回true,这在优先存储空值而不是空或所有空数组时非常有用,例如在更新时触发器中:
NEW.arrvalue := CASE WHEN array_remove(NEW.arrvalue, null) <> '{}' THEN NEW.arrvalue END;