J'utilise le type de tableau natif de Postgres et j'essaie de trouver les enregistrements où l'ID n'est pas dans les ID de destinataire du tableau.
Je peux trouver où ils sont DANS:
SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))
Mais cela ne fonctionne pas:
SELECT COUNT(*) FROM messages WHERE (3 != ANY (recipient_ids))
SELECT COUNT(*) FROM messages WHERE (3 = NOT ANY (recipient_ids))
Quelle est la bonne façon de tester cette condition?
arrays
postgresql
user577808
la source
la source
WHERE 3 NOT IN recipient_ids
marche?text[]
etint[]
tableau:select not(array[1,2,3] @> array[3]);
null
colonne est contenue ou non dans un tableau, elle dira toujours non. Il m'a fallu environ 20 minutes de débogage de plusieurs méthodes contenant pour arriver à la conclusion que vous ne pouvez pas vérifier si null est contenu dans un tableauRéponses:
Vous pouvez toujours nier
WHERE (condition)
avecWHERE NOT (condition)
la source
ANY
au lieu de auIN
fur et à mesure que votrerecipient_ids
liste d'entrées s'allonge: stackoverflow.com/questions/1009706/…Vous pouvez le retourner un peu et dire "3 n'est pas égal à tous les ID":
Du manuel fin :
la source
any
ne fonctionne pas dans ce casany
etall
sur postgres doc, qui dit: "x <> ANY (a,b,c)
équivaut àx <> a OR <> b OR x <> c
". ref: postgresqltutorial.com/postgresql-any postgresqltutorial.com/postgresql-allAugmenter les
ALL/ANY
réponsesJe préfère toutes les solutions qui utilisent
all
ouany
pour obtenir le résultat, en appréciant les notes supplémentaires (par exemple à propos des NULL ). Comme autre augmentation, voici une façon de penser à ces opérateurs.Vous pouvez les considérer comme des opérateurs de court-circuit :
all(array)
parcourt toutes les valeurs du tableau, en les comparant à la valeur de référence à l'aide de l'opérateur fourni. Dès qu'une comparaison aboutitfalse
, le processus se termine par false, sinon true. (Comparable à la logique de court-circuitand
.)any(array)
parcourt toutes les valeurs du tableau, en les comparant à la valeur de référence à l'aide de l'opérateur fourni. Dès qu'une comparaison aboutittrue
, le processus se termine par vrai, sinon faux. (Comparable à la logique de court-circuitor
.)C'est pourquoi
3 <> any('{1,2,3}')
ne donne pas le résultat souhaité: le processus compare 3 à 1 pour l'inégalité, ce qui est vrai, et renvoie immédiatement vrai. Une seule valeur du tableau différente de 3 suffit pour que la condition entière soit vraie. Le 3 dans la dernière position du tableau est prob. jamais utilisé.3 <> all('{1,2,3}')
d'autre part s'assure que toutes les valeurs ne sont pas égales à 3. Il exécutera toutes les comparaisons qui donnent vrai jusqu'à un élément qui donne faux (le dernier dans ce cas), pour retourner faux comme résultat global. C'est ce que veut l'OP.la source
not (3 = any(recipient_ids))
?la source
3 <> ANY(ARRAY[1,2,3,4])
. Cela aurait dû fonctionner de cette façon: \une mise à jour:
à partir de postgres 9.3,
vous pouvez également utiliser
NOT
en tandem avec l'@>
opérateur (contains) pour y parvenir.C'EST À DIRE.
SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];
la source
Méfiez-vous des NULL
Les deux
ALL
:Et
ANY
:Cela fonctionnerait tant que ce
some_array
n'est pas nul Si le tableau peut être nul, vous devez en tenir compte avec coalesce (), par exempleOu
À partir de la documentation :
la source
Notez que les opérateurs ANY / ALL ne fonctionneront pas avec les index de tableau. Si vous pensez aux index:
et le négatif:
Un index peut alors être créé comme:
la source
&&
SELECT COUNT(*) FROM "messages" WHERE ARRAY[3] && recipient_ids
:.