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 ?