PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

L'array è tutti i NULL in PostgreSQL

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

1 e 2 può essere qualsiasi due numeri distinti.

Alternative e prestazioni

Ci sono molti modi. Ho assemblato un test case rapido:

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() richiede Postgres 9.3 o successivo.
array_positions() richiede Postgres 9.5 o successivo.

chk_michael proviene dalla risposta attualmente accettata da @michael .
Le colonne sono in ordine di esecuzione dell'espressione. Il più veloce per primo.
I miei semplici controlli dominano le prestazioni, con array_remove() prossimo. Il resto non può tenere il passo.

L'array vuoto caso speciale ({} ) richiede attenzione. Definisci il risultato atteso e scegli un'espressione adatta o aggiungi un controllo aggiuntivo.

db<>violino qui - con test delle prestazioni
Vecchio sqlfiddle

Come funziona?

L'espressione 1 = ALL(arr) rendimenti:

TRUE .. se tutti gli elementi sono 1
FALSE .. se un elemento è <> 1 (qualsiasi elemento che IS NOT NULL )
NULL .. se almeno un elemento IS NULL e nessun elemento è <> 1

Quindi, se conosciamo un singolo elemento che non può presentarsi (forzato da un CHECK vincolo), come -1 , possiamo semplificare in:

-1 = ALL(arr) IS NULL

Se qualsiasi il numero può apparire, controlla due numeri distinti. Il risultato può essere solo NULL per entrambi se l'array non contiene altro che NULL . Voilà.