PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

É array todos os NULLs no PostgreSQL

1 = ALL(arr) IS NULL AND 2 = ALL(arr) IS NULL

1 e 2 pode ser qualquer dois números distintos.

Alternativas e desempenho


Existem muitos caminhos. Eu montei um caso de teste rápido:
SELECT arr::text
     , -1 = ALL(arr) IS NULL                              AS xsimple
     , 1 = ALL(arr) IS NULL AND 2 = ALL(arr) IS NULL      AS simple
     , array_remove(arr, NULL) = '{}'                     AS array_rem
     , cardinality(array_positions(arr, NULL))
     = cardinality(arr)                                   AS array_pos
     , TRUE = ALL (SELECT unnest(arr) IS NULL)            AS michael
     , (SELECT bool_and(e IS NULL) FROM unnest(arr) e)    AS bool_and
     , NOT EXISTS (SELECT unnest(arr) EXCEPT SELECT null) AS exist
FROM  (
   VALUES
     ('{1,2,NULL,3}'::int[])
   , ('{1,1,1}')
   , ('{2,2,2}')
   , ('{NULL,NULL,NULL}')
   , ('{}'::int[])
   ) t(arr);

       arr        | xsimple | simple | array_rem | array_pos | michael | bool_and | exist 
------------------+---------+--------+-----------+-----------+---------+----------+-------
 {1,2,NULL,3}     | f       | f      | f         | f         | f       | f        | f
 {1,1,1}          | f       | f      | f         | f         | f       | f        | f
 {2,2,2}          | f       | f      | f         | f         | f       | f        | f
 {NULL,NULL,NULL} | t       | t      | t         | t         | t       | t        | t
 {}               | f       | f      | t         | t         | t       |          | t

array_remove() requer o Postgres 9.3 ou posterior.
array_positions() requer Postgres 9.5 ou posterior.

chk_michael é da resposta atualmente aceita por @michael .
As colunas estão na ordem de execução da expressão. Mais rápido primeiro.
Minhas verificações simples dominam o desempenho, com array_remove() próximo. O resto não consegue acompanhar.

A matriz vazia de caso especial ({} ) requer atenção. Defina o resultado esperado e escolha uma expressão de ajuste ou adicione uma verificação adicional.

db<>fiddle aqui - com teste de desempenho
Antigo sqlfiddle

Como funciona?


A expressão 1 = ALL(arr) rendimentos:

TRUE .. se todos os elementos forem 1
FALSE .. se algum elemento for <> 1 (qualquer elemento que IS NOT NULL )
NULL .. se pelo menos um elemento IS NULL e nenhum elemento é <> 1

Então, se conhecemos um único elemento que não pode aparecer (imposto por um CHECK restrição), como -1 , podemos simplificar para:
-1 = ALL(arr) IS NULL

Se qualquer número pode aparecer, verifique se há dois números distintos. O resultado só pode ser NULL para ambos se a matriz não contiver nada além de NULL . Voilá.