É uma maneira de combinar IS DISTINCT FROM
com o postgres ANY
ou alguma outra maneira interessante de obter o mesmo 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 diz que tenta topanswers.xyz
fonte
fonte
IS DISTINCT FROM
ser um operador? Parece apenas uma limitação técnica do analisador e não uma questão semântica.Operador
Isso se baseia no operador inteligente de @ Daniel .
Enquanto estiver nisso, crie a combinação função / operador usando tipos polimórficos . Então funciona para qualquer tipo - assim como a construção.
E faça a função
IMMUTABLE
.Uma pesquisa rápida com o symbolhound apareceu vazia, para que o operador
<!>
não pareça estar em uso em nenhum dos módulos.Se você for usar muito esse operador, poderá aprimorá-lo um pouco mais para ajudar o planejador de consultas ( como o último sugerido em um comentário ). Para iniciantes, você pode adicionar as cláusulas
COMMUTATOR
eNEGATOR
para ajudar o otimizador de consultas. SubstituaCREATE OPERATOR
de cima por este:E adicione:
Mas as cláusulas adicionais não ajudarão no caso de uso em questão e índices simples ainda não serão usados. É muito mais sofisticado conseguir isso. (Não tentei.) Leia o capítulo "Informações sobre otimização do operador" no manual para obter detalhes.
Caso de teste
O caso de teste na pergunta só poderá ter sucesso se todos os valores na matriz forem idênticos. Para a matriz na questão (
'{null,A}'::text[]
), o resultado é sempre VERDADEIRO. Isso é pretendido? Adicionei outro teste para "IS DISTINCT FROM ALL":Alternativa com operadores padrão
quase pode ser traduzido para
foo = ALL (test_arr)
rendimentos ...TRUE
.. se todos os elementos foremfoo
FALSE
.. se algumNOT NULL
elemento for<> foo
NULL
.. se pelo menos um elementoIS NULL
e nenhum elemento for<> foo
Portanto, a caixa de canto restante é onde
-
foo IS NULL
- e
test_arr
consiste em nada além deNULL
elementos.Se qualquer um deles puder ser descartado, estamos prontos. Portanto, use o teste simples se
- a coluna estiver definida
NOT NULL
.- ou você sabe que a matriz nunca é todos os NULLs.
Senão, teste adicionalmente:
Onde
'A'
e'B'
podem ser quaisquer valores distintos. Explicação e alternativas sob esta pergunta relacionada no SO:A matriz é todos os NULLs no PostgreSQL
Novamente, se você souber de algum valor que não possa existir
test_arr
, por exemplo, a sequência vazia''
, ainda poderá simplificar:Aqui está uma matriz de teste completa para verificar todas as combinações:
Isso é um pouco mais detalhado que a
EXCEPT
solução de Andriy , mas é substancialmente mais rápido.fonte
OPERATOR
, a cláusulaCOMMUTATOR
(eNEGATOR
, talvez com oIS NOT DISTINCT FROM
operador inverso ) deve ser fornecida? postgresql.org/docs/current/static/xoper-optimization.htmlapp_status <!> any(array[3,6])
. Infelizmente, isso não afeta os registros. Funciona com números inteiros?