179 votes

Postgres PAS dans le tableau

J'utilise le type de tableau natif de Postgres, et j'essaie de trouver les enregistrements où l'ID n'est pas dans le tableau des ID destinataires.

Je peux trouver où ils se trouvent :

SELECT COUNT(*) FROM messages WHERE (3 = ANY (recipient_ids))

Mais ça ne marche 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 maladie ?

228voto

Frank Farmer Points 16159
SELECT COUNT(*) FROM "messages" WHERE NOT (3 = ANY (recipient_ids))

Vous pouvez toujours nier WHERE (condition) con WHERE NOT (condition)

64voto

mu is too short Points 205090

On pourrait retourner la question et dire "3 n'est pas égal à tous les ID" :

where 3 != all (recipient_ids)

Desde el beau manuel :

9.21.4. ALL (tableau)

expression operator ALL (array expression)

Le côté droit est une expression entre parenthèses, qui doit donner une valeur de tableau. L'expression de gauche est évaluée et comparée à chaque élément du tableau à l'aide de la fonction opérateur qui doit donner un résultat booléen. Le résultat de ALL est "vrai" si toutes les comparaisons donnent vrai (y compris le cas où le tableau a zéro élément). Le résultat est "false" si un résultat faux est trouvé.

44voto

Igal Points 836

Attention aux NULL

Les deux sites ALL :

(some_value != ALL(some_array))

Et ANY :

NOT (some_value = ANY(some_array))

Cela fonctionnerait tant que some_array n'est pas nulle. Si le tableau peut être nul, vous devez en tenir compte avec coalesce(), par exemple.

(some_value != ALL(coalesce(some_array, array[]::int[])))

Ou

NOT (some_value = ANY(coalesce(some_array, array[]::int[])))

Desde el docs :

Si l'expression du tableau donne un tableau nul, le résultat de ANY sera nul.

Si l'expression du tableau donne un tableau nul, le résultat de ALL sera nul.

44voto

ThomasH Points 6597

Augmenter le ALL/ANY Réponses

Je préfère toutes les solutions qui utilisent all o any pour parvenir au résultat, en appréciant les notes supplémentaires (par exemple, à propos de NULL s). En complément, voici une façon de penser à ces opérateurs.

Vous pouvez les considérer comme opérateurs de court-circuit :

  • all(array) passe en revue 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 donne false le processus se termine par un faux, sinon un vrai (comparable à la logique du court-circuit). and .)
  • any(array) passe en revue 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 donne true le processus se termine par un vrai, sinon un faux. (Comparable à la logique du court-circuit or .)

C'est pourquoi 3 <> any('{1,2,3}') ne donne pas le résultat escompté : 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 à rendre la condition entière vraie. Le 3 dans la dernière position du tableau n'est probablement jamais utilisé.

3 <> all('{1,2,3}') d'autre part, s'assure que todo ne sont pas égales 3. Il passera en revue toutes les comparaisons qui donnent un résultat vrai jusqu'à un élément qui donne un résultat faux (le dernier dans ce cas), pour retourner faux comme résultat global. C'est ce que veut l'OP.

19voto

Rooster Points 7528

Une mise à jour :

à partir de postgres 9.3,

vous pouvez utiliser NOT en tandem avec le @> (contient l'opérateur) pour y parvenir également.

IE.

SELECT COUNT(*) FROM "messages" WHERE NOT recipient_ids @> ARRAY[3];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X