Qual é a diferença entre INe ANYoperador no PostgreSQL?
O mecanismo de funcionamento de ambos parece ser o mesmo. Alguém pode explicar isso com um exemplo?
Mas a segunda variante de cada uma não é equivalente à outra. A segunda variante da ANYconstrução leva um array (deve ser um tipo de array real), enquanto a segunda variante de INleva uma lista de valores separados por vírgulas . Isso leva a diferentes restrições na passagem de valores e também pode levar a diferentes planos de consulta em casos especiais:
"Encontrar linhas onde idestá na matriz fornecida":
SELECT*FROM tbl WHERE id =ANY(ARRAY[1,2]);
Inversão: "Encontrar linhas onde nãoid está na matriz":
SELECT*FROM tbl WHERE id <>ALL(ARRAY[1,2]);SELECT*FROM tbl WHERE id <>ALL('{1, 2}');-- equivalent array literalSELECT*FROM tbl WHERENOT(id =ANY('{1, 2}'));
Todos os três equivalentes. O primeiro com construtor de array , os outros dois com literal de array . O tipo de dados pode ser derivado do contexto de forma inequívoca. Caso contrário, um elenco explícito pode ser necessário, como '{1,2}'::int[].
As linhas com id IS NULLnão passam em nenhuma dessas expressões. Para incluir NULLvalores adicionais:
Seria bom esclarecer explicitamente que os resultados das segundas variantes serão sempre os mesmos. Tenho 99% de certeza de que esse é o caso, mas a resposta não parece afirmar isso. O que significa que SELECT * from mytable where id in (1, 2, 3)sempre resultará nas mesmas linhas que SELECT * from mytable where id = ANY('{1, 2, 3}'), mesmo que possam ter planos de consulta diferentes.
KPD
1
ANYnão pode ser combinado com o !=operador. Não acho que esteja documentado, mas select * from foo where id != ANY (ARRAY[1, 2])não é o mesmo que select * from foo where id NOT IN (1, 2). Por outro lado, select * from foo where NOT (id = ANY (ARRAY[1, 2]))funciona como esperado.
qris
1
@qris: ANYpode ser combinado com o !=operador. Mas há mais do que isso. Eu adicionei um capítulo acima. (Observe que <>é o operador no SQL padrão - embora também !=seja aceito no Postgres.)
Erwin Brandstetter
Como funciona a última versão que inclui NULLvalores? Funcionaria WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;tão bem?
dvtan
1
@dvtan: (id = ...) IS NOT TRUEfunciona porque id = ...só avalia TRUEse há uma correspondência real. Resultados FALSEou NULLpassar no nosso teste. Consulte: stackoverflow.com/a/23767625/939860 . Sua expressão adicionada testa para outra coisa. Isso seria equivalenteWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter
3
Existem dois pontos óbvios, bem como os pontos na outra resposta:
Eles são exatamente equivalentes ao usar subconsultas:
Respostas:
(Nem
IN
nemANY
é um "operador". Uma "construção" ou "elemento de sintaxe".)Logicamente , citando o manual :
Mas existem duas variantes de sintaxe de
IN
e duas variantes deANY
. Detalhes:IN
pegar um conjunto é equivalente a= ANY
pegar um conjunto , conforme demonstrado aqui:Mas a segunda variante de cada uma não é equivalente à outra. A segunda variante da
ANY
construção leva um array (deve ser um tipo de array real), enquanto a segunda variante deIN
leva uma lista de valores separados por vírgulas . Isso leva a diferentes restrições na passagem de valores e também pode levar a diferentes planos de consulta em casos especiais:=any()
mas usado comin
ANY
é mais versátilA
ANY
construção é muito mais versátil, pois pode ser combinada com vários operadores, não apenas=
. Exemplo:Para um grande número de valores, fornecer um conjunto de escalas melhor para cada um:
Relacionado:
Inversão / oposto / exclusão
"Encontrar linhas onde
id
está na matriz fornecida":Inversão: "Encontrar linhas onde não
id
está na matriz":Todos os três equivalentes. O primeiro com construtor de array , os outros dois com literal de array . O tipo de dados pode ser derivado do contexto de forma inequívoca. Caso contrário, um elenco explícito pode ser necessário, como
'{1,2}'::int[]
.As linhas com
id IS NULL
não passam em nenhuma dessas expressões. Para incluirNULL
valores adicionais:fonte
SELECT * from mytable where id in (1, 2, 3)
sempre resultará nas mesmas linhas queSELECT * from mytable where id = ANY('{1, 2, 3}')
, mesmo que possam ter planos de consulta diferentes.ANY
não pode ser combinado com o!=
operador. Não acho que esteja documentado, masselect * from foo where id != ANY (ARRAY[1, 2])
não é o mesmo queselect * from foo where id NOT IN (1, 2)
. Por outro lado,select * from foo where NOT (id = ANY (ARRAY[1, 2]))
funciona como esperado.ANY
pode ser combinado com o!=
operador. Mas há mais do que isso. Eu adicionei um capítulo acima. (Observe que<>
é o operador no SQL padrão - embora também!=
seja aceito no Postgres.)NULL
valores? FuncionariaWHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;
tão bem?(id = ...) IS NOT TRUE
funciona porqueid = ...
só avaliaTRUE
se há uma correspondência real. ResultadosFALSE
ouNULL
passar no nosso teste. Consulte: stackoverflow.com/a/23767625/939860 . Sua expressão adicionada testa para outra coisa. Isso seria equivalenteWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Existem dois pontos óbvios, bem como os pontos na outra resposta:
Eles são exatamente equivalentes ao usar subconsultas:
Por outro lado:
Apenas o
IN
operador permite uma lista simples:Presumir que eles são exatamente os mesmos me surpreendeu várias vezes quando esqueci que
ANY
não funciona com listas.fonte