MySQL: Filtragem avançada e consultas com expressões…
Última atualização: 2026-08-26
Quando a filtragem básica não é suficiente, a filtragem avançada permite identificar dados específicos.
Esta aula oferece uma explicação detalhada sobre combinações condicionais complexas e expressões regulares.
graph TB
A[WHERE Combinations of Conditions] --> B[AND Logic and]
A --> C[OR Logical OR]
A --> D[NOT Negate]
B --> E[All conditions are met simultaneously]
C --> F[Meets any one of the conditions]
A --> G[IN List Matching]
A --> H[BETWEEN Scope]
A --> I[LIKE Wildcard]
A --> J[REGEXP Regular]
A --> K[EXISTS Subquery]
1. O que você vai aprender
- Combinações de condições “E”/“OU”
- Consulta de lista “IN/NOT IN”
- Consulta de intervalo BETWEEN
- Correspondência com o caractere curinga LIKE
- REGEXP: Expressões regulares
2. Uma história real sobre um recurso de busca
(1) Problema: Resultados de pesquisa imprecisos
Um usuário pesquisa por “john” e solicita uma correspondência para:
- John Smith
- JOHNSON
- john@example.com Ah, John
O simples LIKE '%john%' só pode corresponder a um cenário.
(2) A solução com REGEXP
SELECT * FROM users
WHERE first_name REGEXP '^john|john$|john'
OR email REGEXP 'john';
3. ANÁLISE APROFUNDADA DE AND/OR
▶ Exemplo: Combinações complexas de condições
-- Search: Engineering or Sales department, and salary > 5000
SELECT * FROM employees
WHERE (department = 'Engineering' OR department = 'Sales')
AND salary > 5000;
-- Search: Salary 5000-8000, not HR department
SELECT * FROM employees
WHERE salary BETWEEN 5000 AND 8000
AND department != 'HR';
-- Search: Hired after 2024, or salary > 10000
SELECT * FROM employees
WHERE hire_date >= '2024-01-01' OR salary > 10000;
4. DENTRO/FORA
▶ Exemplo: Consulta de lista
-- IN Search
SELECT * FROM products WHERE category_id IN (1, 3, 5, 7);
-- NOT IN Search
SELECT * FROM products WHERE category_id NOT IN (2, 4, 6);
-- Subquery IN
SELECT * FROM employees
WHERE department_id IN (SELECT id FROM departments WHERE location = 'Beijing');
-- NOT EXISTS replacement for NOT IN (Better performance)
SELECT * FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
5. BETWEEN avançado
▶ Exemplo: Consulta por intervalo
-- Value Range
SELECT * FROM products WHERE price BETWEEN 100 AND 500;
-- Date Range
SELECT * FROM orders WHERE order_date BETWEEN '2026-01-01' AND '2026-06-30';
-- String Range
SELECT * FROM employees WHERE last_name BETWEEN 'A' AND 'M';
-- NOT BETWEEN
SELECT * FROM products WHERE price NOT BETWEEN 100 AND 500;
6. O caractere curinga LIKE
▶ Exemplo: Correspondência aproximada
-- % Match any number of characters (including 0)
SELECT * FROM users WHERE name LIKE 'J%'; -- Starts with J
SELECT * FROM users WHERE name LIKE '%son'; -- Ends with son
SELECT * FROM users WHERE name LIKE '%john%'; -- Contains john
-- _ Matches exactly one character
SELECT * FROM users WHERE name LIKE 'J_hn'; -- J_hn (John, Johan)
-- Used in combination
SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- ESCAPE escaping special characters
SELECT * FROM files WHERE name LIKE '%\_%' ESCAPE '\\'; -- Contains _
SELECT * FROM files WHERE name LIKE '%%' ESCAPE '\\'; -- Contains %
7. REGEXP: Expressões regulares
(1) Metacaracteres comuns em expressões regulares
| Metacaractere | Descrição | Exemplo |
|---|---|---|
^ |
Início | '^John' — Começa com John |
$ |
Fim | 'son$' — Termina com “filho” |
. |
Qualquer caractere | 'J.hn' — John, Johan |
[...] |
Conjunto de caracteres | '[abc]' — um dos seguintes: a/b/c |
[^...] |
Excluir conjunto de caracteres | [^abc] — Não é a/b/c |
* |
0 vezes ou mais | 'ab*' — a, ab, abb |
+ |
uma vez ou mais | 'ab+' — a, ab |
? |
0 vezes ou 1 vez | 'ab?' — a, ab |
{n} |
exatamente n vezes | 'a{3}' — aaa |
{n,m} |
n a m vezes | 'a{2,4}' — aa~aaaa |
| |
OU | 'cat|dog' — gato ou cachorro |
▶ Exemplo: Consulta REGEXP
-- Starts with J or j
SELECT * FROM users WHERE first_name REGEXP '^[Jj]';
-- Contains numbers
SELECT * FROM users WHERE username REGEXP '[0-9]';
-- Email format validation (Simple)
SELECT * FROM users WHERE email REGEXP '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$';
-- Mobile phone number format (Mainland China)
SELECT * FROM users WHERE phone REGEXP '^1[3-9][0-9]{9}$';
-- Contains CJK characters
SELECT * FROM users WHERE name REGEXP '[\\u4e00-\\u9fff]';
▶ Exemplo: REGEXP x LIKE
-- LIKE matches must be at the beginning and end only
SELECT * FROM users WHERE name LIKE '%john%'; -- Contains john
-- REGEXP allows for precise control
SELECT * FROM users WHERE name REGEXP '^john$'; -- Exactly equal to john (Case-insensitive)
SELECT * FROM users WHERE name REGEXP 'john|jane'; -- john or jane
SELECT * FROM users WHERE name REGEXP '^[A-Z]'; -- Starts with a capital letter
8. Subconsultas EXISTS
▶ Exemplo: Como usar EXISTS
-- Query Customers with Orders
SELECT * FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
-- Query Customers with No Orders
SELECT * FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);
❓ Perguntas Frequentes
P: Uma consulta
LIKE '%keyword%'pode usar um índice? R: Se o prefixo contiver%, ela não poderá usar um índice e realizará uma varredura completa da tabela. Para conjuntos de dados grandes, considere usar um índice de texto completo (FULLTEXT).
P: O que é mais rápido, REGEXP ou LIKE? R: O LIKE costuma ser mais rápido (pode usar índices). O REGEXP é mais flexível, mas não pode usar índices (suportado parcialmente no MySQL 8.0).
P: O que tem melhor desempenho, IN ou OR? R: Ambos apresentam desempenho semelhante quando há poucos dados. Quando a lista IN é longa, o MySQL a otimiza para uma busca binária ordenada, que é mais rápida do que OR.
P: Existe uma armadilha com NULL ao usar NOT IN? R: Sim.
NOT IN (1, 2, NULL)sempre retorna NULL porque uma comparação envolvendo NULL resulta em NULL. Use NOT EXISTS em vez disso.
📖 Resumo
- E/OU condições combinadas; use parênteses para especificar a ordem das operações
- Consultas à lista IN/NOT IN: Cuidado com as armadilhas do NULL
- Consulta de intervalo ENTRE, incluindo ambos os extremos
- LIKE: caractere curinga:
%qualquer número de caracteres,_um único caractere - REGEXP Expressões regulares; suporta correspondência de padrões complexos
- Verificação de existência por subconsulta EXISTS; o desempenho é geralmente melhor do que o da cláusula IN
📝 Exercícios
-
Questão básica (Dificuldade: ⭐): Use uma consulta LIKE para encontrar usuários cujos endereços de e-mail contenham “@gmail.com” e cujos nomes de usuário comecem com “J”.
-
Problema avançado (Dificuldade ⭐⭐): Use REGEXP para identificar números de celular da China continental (que começam com 1, cujo segundo dígito é um número entre 3 e 9 e que têm um total de 11 dígitos).
-
Questão de desafio (Dificuldade: ⭐⭐⭐): Compare as diferenças nos resultados das consultas entre
NOT INeNOT EXISTSquando há valores NULL.