PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment utiliser ANY au lieu de IN dans une clause WHERE avec Rails ?

Il existe deux variantes de IN expression :

  • expression IN (subquery)
  • expression IN (value [, ...])

De même, deux variantes avec le ANY construire :

  • expression operator ANY (subquery)
  • expression operator ANY (array expression)

Une sous-requête fonctionne pour les deux techniques, mais pour la seconde forme de chacun, IN attend une liste de valeurs (tel que défini en SQL standard) tant que = ANY attend un tableau .

Lequel utiliser ?

ANY est un ajout ultérieur, plus polyvalent, il peut être combiné avec n'importe quel opérateur binaire renvoyant une valeur booléenne. IN se réduit à un cas particulier de ANY . En fait, sa deuxième forme est réécrite en interne :

IN est réécrit avec = ANY
NOT IN est réécrit avec <> ALL

Vérifiez le EXPLAIN sortie pour toute requête à voir par vous-même. Cela prouve deux choses :

  • IN ne peut jamais être plus rapide que = ANY .
  • = ANY ne sera pas sensiblement plus rapide.

Le choix doit être décidé par ce qui est plus facile à fournir  :une liste de valeurs ou un tableau (éventuellement sous forme de littéral de tableau - une valeur unique).

Si les identifiants que vous allez transmettre proviennent de la base de données de toute façon, il est beaucoup plus efficace de les sélectionner directement (sous-requête) ou d'intégrer la table source dans la requête avec un JOIN (comme @mu a commenté).

Pour passer une longue liste des valeurs de votre client et obtenez les meilleures performances , utilisez un tableau, unnest() et joindre, ou fournissez-le comme expression de table en utilisant VALUES (comme @PinnyM a commenté). Mais notez qu'un JOIN préserve les doublons possibles dans le tableau fourni / set while IN ou = ANY ne pas. Plus :

  • Optimiser une requête Postgres avec un grand IN

En présence de valeurs NULL, NOT IN est souvent le mauvais choix et NOT EXISTS serait juste (et plus rapide aussi):

  • Sélectionnez les lignes qui ne sont pas présentes dans un autre tableau

Syntaxe pour = ANY

Pour l'expression de tableau que Postgres accepte :

  • un constructeur de tableaux (le tableau est construit à partir d'une liste de valeurs côté Postgres) de la forme :ARRAY[1,2,3]
  • ou un littéral de tableau de la forme '{1,2,3}' .

Pour éviter les conversions de type invalides, vous pouvez convertir explicitement :

ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]

Connexe :

  • PostgreSQL :problème lors du passage du tableau à la procédure
  • Comment passer un tableau de types personnalisés à la fonction Postgres

Ou vous pourriez créer une fonction Postgres prenant un VARIADIC paramètre, qui prend des arguments individuels et forme un tableau à partir d'eux :

  • Passer plusieurs valeurs dans un seul paramètre

Comment passer le tableau depuis Ruby ?

En supposant id être integer :

MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})

Mais je ne fais que barboter dans Ruby. @mu fournit des instructions détaillées dans cette réponse connexe :

  • Envoi d'un tableau de valeurs à une requête sql en ruby ?