Esistono due varianti di IN
espressioni:
expression IN (subquery)
expression IN (value [, ...])
Allo stesso modo, due varianti con ANY
costruire:
expression operator ANY (subquery)
expression operator ANY (array expression)
Una sottoquery funziona per entrambe le tecniche, ma per la seconda forma di ciascuno, IN
si aspetta un elenco di valori (come definito nell'SQL standard) mentre = ANY
si aspetta un array .
Quale usare?
ANY
è un'aggiunta successiva e più versatile, può essere combinata con qualsiasi operatore binario che restituisca un valore booleano. IN
si riduce a un caso speciale di ANY
. Infatti, la sua seconda forma viene riscritta internamente:
IN
viene riscritto con = ANY
NOT IN
viene riscritto con <> ALL
Controlla il EXPLAIN
output per qualsiasi query da visualizzare di persona. Questo dimostra due cose:
IN
non può mai essere più veloce di= ANY
.= ANY
non sarà sostanzialmente più veloce.
La scelta dovrebbe essere decisa da cosa è più facile fornire :un elenco di valori o un array (possibilmente come array letterale - un singolo valore).
Se gli ID che intendi trasmettere provengono dall'interno del DB in ogni caso, è molto più efficiente selezionarli direttamente (subquery) o integrare la tabella sorgente nella query con un JOIN
(come ha commentato @mu).
Per superare un elenco lungo di valori dal tuo cliente e ottieni le migliori performance , usa un array, unnest()
e unisciti o forniscilo come espressione di tabella utilizzando VALUES
(come ha commentato @PinnyM). Ma nota che un JOIN
conserva possibili duplicati nell'array/set fornito mentre IN
o = ANY
non. Altro:
- Ottimizzazione di una query Postgres con un IN grande
In presenza di valori NULL, NOT IN
è spesso la scelta sbagliata e NOT EXISTS
sarebbe giusto (e anche più veloce):
- Seleziona le righe che non sono presenti in un'altra tabella
Sintassi per = ANY
Per l'espressione di matrice Postgres accetta:
- un costruttore di array (l'array è costruito da un elenco di valori sul lato Postgres) del modulo:
ARRAY[1,2,3]
- o un letterale array del modulo
'{1,2,3}'
.
Per evitare cast di tipi non validi, puoi trasmettere in modo esplicito:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Correlati:
- PostgreSQL:problema con il passaggio dell'array alla procedura
- Come passare un array di tipi personalizzati alla funzione Postgres
Oppure potresti crea una funzione Postgres prendendo un VARIADIC
parametro, che prende i singoli argomenti e ne forma una matrice:
- Passaggio di più valori in un singolo parametro
Come passare l'array da Ruby?
Assumendo id
essere integer
:
MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Ma mi sto solo dilettando con Ruby. @mu fornisce istruzioni dettagliate in questa risposta correlata:
- Invio di una matrice di valori a una query sql in ruby?