SQL IN: filtragem de linhas com listas

O operador SQL IN testa se um valor corresponde a qualquer elemento de uma lista. Um predicado SQL WHERE IN substitui cadeias longas de OR ao filtrar por um conjunto conhecido de valores discretos, como códigos de status, nomes de categoria e IDs de região. Use uma lista SQL WHERE IN quando os valores são conhecidos de antemão e a condição precisa continuar legível conforme cresce.

Exemplo de SQL IN para correspondência por lista

Saída:

A saída aparecerá aqui...

Saída:

+----------+-------------+
| nome     | categoria   |
+----------+-------------+
| Borracha | papelaria   |
| Caderno  | papelaria   |
| Mouse    | eletronicos |
| Teclado  | eletronicos |
+----------+-------------+
4 row(s)

Como este exemplo funciona

  1. CREATE TABLE e INSERT populam uma tabela produtos com cinco linhas em três categorias.
  2. WHERE categoria IN ('eletronicos', 'papelaria') corresponde a qualquer linha cuja categoria seja igual a um dos valores listados. Em termos lógicos, isso equivale a categoria = 'eletronicos' OR categoria = 'papelaria'.
  3. A linha moveis é excluída porque sua categoria não está na lista.
  4. ORDER BY nome deixa a saída determinística.

IN com uma lista literal é equivalente a comparações encadeadas com OR, mas escala melhor conforme o conjunto cresce: adicionar um valor significa incluir mais um item na lista, não mais uma cláusula OR.

O que é o operador SQL IN?

O operador SQL IN é uma forma curta de várias comparações de igualdade unidas por OR. WHERE x IN (a, b, c) é logicamente idêntico a WHERE x = a OR x = b OR x = c. Na lógica ternária do SQL, se nenhum elemento da lista corresponder e não houver NULL, IN retorna falso. Se existir NULL e não houver correspondência exata, o resultado é desconhecido; em uma cláusula WHERE, esse resultado filtra a linha.

Como lidar com uma lista SQL WHERE IN vazia

A maioria dos bancos rejeita WHERE col IN () com erro de sintaxe, algo comum em consultas geradas dinamicamente. Trate o caso vazio de forma explícita: pule o filtro ou force um predicado sempre falso, como WHERE 1 = 0, quando uma lista vazia deve retornar zero linhas.

SQL NOT IN e a armadilha do NULL

SQL NOT IN inverte a verificação: retorna verdadeiro apenas quando o valor é diferente de todos os elementos da lista. Um único NULL na lista pode transformar o resultado em desconhecido porque x <> NULL é sempre desconhecido, e WHERE trata desconhecido como falso:

-- Retorna 0 linhas: o NULL torna o predicado UNKNOWN
SELECT nome
FROM produtos
WHERE categoria NOT IN ('eletronicos', NULL);

Quando a lista vem de uma subconsulta, filtre NULLs dentro da subconsulta ou use NOT EXISTS para ter semântica segura com NULL.

IN com subconsultas

IN também aceita uma subconsulta no lugar de uma lista literal. Conceitualmente, a subconsulta produz um conjunto de valores, e a consulta externa verifica pertencimento:

SELECT nome FROM produtos
WHERE categoria IN (
  SELECT categoria FROM produtos WHERE nome LIKE '%ado%'
);

Para subconsultas pequenas e não correlacionadas, isso funciona bem. Quando a subconsulta retorna muitas linhas ou envolve correlação, EXISTS ou JOIN costuma performar melhor porque o otimizador pode aplicar estratégias de semi-join.

IN vs EXISTS vs JOIN

AbordagemUse quando…
IN (lista)Filtrar por um conjunto pequeno e conhecido de valores literais
IN (subconsulta)Verificar pertencimento em um resultado pequeno e não anulável
EXISTS (subconsulta)Verificação correlacionada ou chaves estrangeiras anuláveis
JOINVocê precisa de colunas das duas tabelas na saída
BETWEENOs valores formam um intervalo contínuo, não itens discretos

Regra: use IN para conjuntos discretos de valores. Troque para EXISTS quando a subconsulta for correlacionada ou anulável. Use JOIN quando precisar de dados dos dois lados.

Notas de desempenho

IN em uma coluna indexada é sargable: o otimizador pode fazer buscas de índice para cada valor da lista. Alguns mecanismos ordenam listas IN literais internamente para avaliação por busca binária. Listas literais muito grandes (centenas de valores) podem tornar o parsing e a geração de plano mais lentos; nesse caso, carregue os valores em uma tabela temporária e faça JOIN.

FAQ

SQL IN é o mesmo que múltiplas condições OR?

No plano lógico, sim. WHERE x IN (1, 2, 3) equivale a WHERE x = 1 OR x = 2 OR x = 3. O otimizador normalmente gera o mesmo plano para as duas formas, mas IN é mais curto e mais fácil de manter conforme a lista cresce.

Por que NOT IN não retorna linhas quando a subconsulta contém NULL?

NOT IN se expande para uma cadeia de comparações com AND: x <> a AND x <> b AND x <> NULL. Como x <> NULL é sempre desconhecido, a expressão inteira nunca é verdadeira. Filtre NULLs da subconsulta ou use NOT EXISTS para evitar esse comportamento.

Posso usar IN com uma subconsulta?

Sim. WHERE col IN (SELECT col FROM outra_tabela) verifica pertencimento no resultado da subconsulta. Para conjuntos pequenos e não anuláveis, isso costuma ser eficiente. Para conjuntos grandes ou anuláveis, EXISTS ou JOIN geralmente dão mais flexibilidade ao otimizador.