Es una manera de combinar postgres IS DISTINCT FROM
con ANY
o alguna otra forma elegante de conseguir el mismo resultado?
select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo <> any(array[null, 'A']);
count
-------
1
(1 row)
select count(*)
from (select 'A' foo union all select 'Z' union all select null) z
where foo is distinct from any(array[null, 'A']);
ERROR: syntax error at or near "any"
LINE 3: where foo is distinct from any(array[null, 'A']);
^
postgresql
null
postgresql-9.3
Jack dice que intente topanswers.xyz
fuente
fuente
IS DISTINCT FROM
ser un operador? Parece solo una limitación técnica del analizador en lugar de un problema semántico.Operador
Esto se basa en el operador inteligente de @Daniel .
Mientras lo hace, cree el combo de función / operador utilizando tipos polimórficos . Entonces funciona para cualquier tipo, al igual que la construcción.
Y hacer la función
IMMUTABLE
.Una búsqueda rápida con Symbolhound quedó vacía, por lo que el operador
<!>
no parece estar en uso en ninguno de los módulos.Si va a utilizar mucho este operador, puede desarrollarlo un poco más para ayudar al planificador de consultas ( como los sugeridos en un comentario ). Para empezar, puede agregar las cláusulas
COMMUTATOR
yNEGATOR
para ayudar al optimizador de consultas. ReemplazarCREATE OPERATOR
desde arriba con esto:Y añadir:
Pero las cláusulas adicionales no ayudarán con el caso de uso en cuestión y los índices simples todavía no se utilizarán. Es mucho más sofisticado lograr eso. (No lo he intentado). Lea el capítulo "Información de optimización del operador" en el manual para obtener más detalles.
Caso de prueba
El caso de prueba en la pregunta solo puede tener éxito si todos los valores de la matriz son idénticos. Para la matriz en la pregunta (
'{null,A}'::text[]
) el resultado es siempre VERDADERO. ¿Es eso intencionado? Agregué otra prueba para "ES DISTINTO DE TODO":Alternativa con operadores estándar
puede casi ser traducido a
foo = ALL (test_arr)
rinde ...TRUE
.. si todos los elementos sonfoo
FALSE
.. si algúnNOT NULL
elemento es<> foo
NULL
.. si al menos un elementoIS NULL
y ningún elemento es<> foo
Entonces, el caso de la esquina restante es donde
-
foo IS NULL
- y
test_arr
consiste en nada más queNULL
elementos.Si cualquiera de los dos puede descartarse, ya hemos terminado. Por lo tanto, use la prueba simple if
- la columna está definida
NOT NULL
.- o que sabe la matriz no es todos los valores NULL.
De lo contrario, prueba adicionalmente:
Donde
'A'
y'B'
puede ser cualquier valor distinto. Explicación y alternativas bajo esta pregunta relacionada sobre SO:¿Es la matriz todos NULL en PostgreSQL
Nuevamente, si conoce algún valor que no puede existir
test_arr
, por ejemplo, la cadena vacía''
, aún puede simplificar:Aquí hay una matriz de prueba completa para verificar todas las combinaciones:
Esto es un poco más detallado que la
EXCEPT
solución de Andriy , pero es sustancialmente más rápido.fuente
OPERATOR
, caso de que elCOMMUTATOR
(yNEGATOR
, tal vez con la inversaIS NOT DISTINCT FROM
del operador) Cláusula suministrar? postgresql.org/docs/current/static/xoper-optimization.htmlapp_status <!> any(array[3,6])
. Desafortunadamente, no tiene ningún efecto en los registros. ¿Funciona con enteros?