Existem duas variantes de
IN
expressões:expression IN (subquery)
expression IN (value [, ...])
Da mesma forma, duas variantes com o
ANY
construir:expression operator ANY (subquery)
expression operator ANY (array expression)
Uma subconsulta funciona para qualquer técnica, mas para o segundo forma de cada um,
IN
espera uma lista de valores (conforme definido no SQL padrão) enquanto = ANY
espera uma matriz . Qual usar?
ANY
é uma adição posterior e mais versátil, pode ser combinada com qualquer operador binário retornando um valor booleano. IN
reduz a um caso especial de ANY
. De fato, sua segunda forma é reescrita internamente:IN
é reescrito com = ANY
NOT IN
é reescrito com <> ALL
Verifique o
EXPLAIN
saída para qualquer consulta para ver por si mesmo. Isso prova duas coisas:IN
nunca pode ser mais rápido que= ANY
.= ANY
não será substancialmente mais rápido.
A escolha deve ser decidida por o que é mais fácil de fornecer :uma lista de valores ou um array (possivelmente como array literal - um único valor).
Se os IDs que você vai passar vierem de dentro do banco de dados de qualquer forma, é muito mais eficiente selecioná-los diretamente (subconsulta) ou integrar a tabela de origem na consulta com um
JOIN
(como @mu comentou). Para passar uma lista longa de valores do seu cliente e obtenha o melhor desempenho , use uma matriz,
unnest()
e juntar, ou fornecê-lo como expressão de tabela usando VALUES
(como @PinnyM comentou). Mas observe que um JOIN
preserva possíveis duplicações no array fornecido / set enquanto IN
ou = ANY
não faça. Mais:- Otimizando uma consulta Postgres com um grande IN
Na presença de valores NULL,
NOT IN
geralmente é a escolha errada e NOT EXISTS
estaria certo (e mais rápido também):- Selecione as linhas que não estão presentes em outra tabela
Sintaxe para = ANY
Para a expressão de array, o Postgres aceita:
- um construtor de matriz (array é construído a partir de uma lista de valores no lado do Postgres) da forma:
ARRAY[1,2,3]
- ou um literal de matriz da forma
'{1,2,3}'
.
Para evitar conversões de tipo inválido, você pode converter explicitamente:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Relacionado:
- PostgreSQL:problema ao passar array para procedimento
- Como passar array de tipo personalizado para a função Postgres
Ou você poderia crie uma função Postgres pegando um
VARIADIC
parâmetro, que recebe argumentos individuais e forma um array a partir deles:- Passando vários valores em um único parâmetro
Como passar o array do Ruby?
Assumindo
id
para ser integer
:MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Mas estou apenas brincando com Ruby. @mu fornece instruções detalhadas nesta resposta relacionada:
- Enviando array de valores para uma consulta sql em ruby?