arrays - llenar - Postgres NO en matriz
recorrer array postgresql (7)
Cuidado con NULLs
Ambos, ALL
:
(some_value != ALL(some_array))
Y ANY
:
NOT (some_value = ANY(some_array))
some_array
siempre que some_array
no sea nulo. Si la matriz puede ser nula, entonces debe contabilizarla con coalesce (), por ej.
(some_value != ALL(coalesce(some_array, array[]::int[])))
O
NOT (some_value = ANY(coalesce(some_array, array[]::int[])))
De los docs :
Si la expresión de matriz produce una matriz nula, el resultado de CUALQUIER será nulo
Si la expresión del array produce una matriz nula, el resultado de ALL será nulo
Estoy usando el tipo de matriz nativa de Postgres e intento encontrar los registros donde la ID no está en los ID de los destinatarios de la matriz.
Puedo encontrar dónde están EN:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Pero esto no funciona:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
¿Cuál es la forma correcta de evaluar esta condición?
Aumentando ALL/ANY
Respuestas
Prefiero todas las soluciones que usan all
o any
para lograr el resultado, apreciando las notas adicionales (por ejemplo, sobre NULL s). Como otra augementación, aquí hay una forma de pensar sobre esos operadores.
Puede pensar en ellos como operadores de cortocircuito :
-
all(array)
pasa por todos los valores de la matriz, comparando cada uno con el valor de referencia utilizando el operador proporcionado. Tan pronto como una comparación arroja resultadosfalse
, el proceso termina con falso, de lo contrario es cierto. (Comparable a cortocircuito lógicoand
.) -
any(array)
pasa por todos los valores de la matriz, comparando cada uno con el valor de referencia utilizando el operador proporcionado. Tan pronto como una comparación setrue
, el proceso finaliza con verdadero, de lo contrario falso. (Comparable a cortocircuito lógicoor
)
Esta es la razón por la cual 3 <> any(''{1,2,3}'')
no produce el resultado deseado: el proceso compara 3 con 1 para desigualdad, que es verdadero, y devuelve inmediatamente verdadero. Un único valor en la matriz diferente de 3 es suficiente para hacer que la condición sea verdadera. El 3 en la última posición de la matriz es prob. nunca usado.
3 <> all(''{1,2,3}'')
por otra parte se asegura de que todos los valores no sean iguales 3. Se ejecutará a través de todas las comparaciones que den como resultado verdadero hasta un elemento que arroje falso (el último en este caso ), para devolver falso como el resultado global. Esto es lo que quiere el OP.
Podría darle la vuelta un poco y decir "3 no es igual a todas las ID":
where 3 != all (recipient_ids)
Del fino manual :
9.21.4. TODO (matriz)
expression operator ALL (array expression)
El lado derecho es una expresión entre paréntesis, que debe producir un valor de matriz. La expresión de la izquierda se evalúa y compara con cada elemento de la matriz utilizando el operador dado, que debe producir un resultado booleano. El resultado de
ALL
es "verdadero" si todas las comparaciones son verdaderas (incluido el caso en que la matriz tiene cero elementos). El resultado es "falso" si se encuentra un resultado falso.
Tenga en cuenta que los operadores ANY / ALL no funcionarán con índices de matriz. Si los índices están en mente:
SELECT COUNT(*) FROM "messages" WHERE 3 && recipient_ids
y lo negativo:
SELECT COUNT(*) FROM "messages" WHERE NOT (3 && recipient_ids)
Un índice puede ser creado como:
CREATE INDEX recipient_ids_idx on tableName USING GIN(recipient_ids)
una actualización:
a partir de postgres 9.3,
puede usar NOT
en tándem con @>
(contains operator) para lograr esto también.
ES DECIR.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
not (3 = any(recipient_ids))
?
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))
Siempre puede negar WHERE (condition)
con WHERE NOT (condition)