Est-ce un moyen postgres de combiner IS DISTINCT FROM
avec ANY
ou une autre façon soignée d'obtenir le même résultat?
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']);
^
la source
IS DISTINCT FROM
être un opérateur? Cela ressemble à une limitation technique de l'analyseur plutôt qu'à un problème sémantique.Opérateur
Cela s'appuie sur l'opérateur intelligent de @ Daniel .
Tout en y étant, créez le combo fonction / opérateur en utilisant des types polymorphes . Ensuite, cela fonctionne pour tout type - tout comme la construction.
Et faites la fonction
IMMUTABLE
.Une recherche rapide avec symbolhound est apparue vide, de sorte que l'opérateur
<!>
ne semble pas être utilisé dans aucun des modules.Si vous utilisez beaucoup cet opérateur, vous pouvez l'étoffer davantage pour aider le planificateur de requêtes ( comme losthorse l'a suggéré dans un commentaire ). Pour commencer, vous pouvez ajouter les clauses
COMMUTATOR
etNEGATOR
pour aider l'optimiseur de requête. RemplacezCREATE OPERATOR
par le haut par ceci:Et ajouter:
Mais les clauses supplémentaires n'aideront pas avec le cas d'utilisation à portée de main et les index simples ne seront toujours pas utilisés. C'est beaucoup plus sophistiqué pour y parvenir. (Je n'ai pas essayé.) Lisez le chapitre "Informations sur l'optimisation de l'opérateur" dans le manuel pour plus de détails.
Cas de test
Le scénario de test dans la question ne peut réussir que si toutes les valeurs du tableau sont identiques. Pour le tableau dans la question (
'{null,A}'::text[]
), le résultat est toujours VRAI. Est-ce prévu? J'ai ajouté un autre test pour "EST DISTINCT DE TOUS":Alternative avec opérateurs standard
peut presque être traduit en
foo = ALL (test_arr)
rendements ...TRUE
.. si tous les éléments sontfoo
FALSE
.. si unNOT NULL
élément est<> foo
NULL
.. si au moins un élémentIS NULL
et aucun élément n'est<> foo
Ainsi, le cas d'angle restant est où
-
foo IS NULL
- et ne se
test_arr
compose que d'NULL
éléments.Si l'un ou l'autre peut être exclu, nous avons terminé. Par conséquent, utilisez le test simple si
- la colonne est définie
NOT NULL
.- ou vous savez que le tableau n'est jamais entièrement NULL.
Sinon, testez en plus:
Où
'A'
et'B'
peut être des valeurs distinctes. Explication et alternatives sous cette question connexe sur SO: letableau est-il tous NULL dans PostgreSQL
Encore une fois, si vous connaissez une valeur qui ne peut pas exister dans
test_arr
, par exemple la chaîne vide''
, vous pouvez toujours simplifier:Voici une matrice de test complète pour vérifier toutes les combinaisons:
C'est un peu plus verbeux que la
EXCEPT
solution d' Andriy , mais c'est beaucoup plus rapide.la source
OPERATOR
, la clauseCOMMUTATOR
(etNEGATOR
, peut-être avec l'IS NOT DISTINCT FROM
opérateur inverse ) doit-elle être fournie? postgresql.org/docs/current/static/xoper-optimization.htmlapp_status <!> any(array[3,6])
. Malheureusement, cela n'a aucun effet sur les enregistrements. Fonctionne-t-il avec des entiers?