Uma subconsulta é uma consulta SQL (Structured Query Language) que está aninhada em outra consulta SQL. O comando no qual a subconsulta está aninhada é chamado de consulta pai. As subconsultas são usadas para pré-processar dados usados na consulta pai. As subconsultas podem ser aplicadas em
SELECT
, INSERT
, UPDATE
e DELETE
operações. Quando as subconsultas são executadas, a subconsulta é processada primeiro antes da consulta pai. Ao construir aplicativos MySQL, o uso de subconsultas oferece várias vantagens:
- Eles dividem as instruções SQL em unidades lógicas simples, o que pode torná-las mais fáceis de entender e manter. Em outras palavras, as subconsultas ajudam a isolar partes complexas das consultas.
- Eles eliminam a necessidade de usar
UNION
complexos declarações eJOIN
declarações. - Eles são usados para reforçar a integridade referencial em um cenário em que as chaves estrangeiras não são implementadas.
- Eles ajudam os desenvolvedores a codificar a lógica de negócios nas consultas do MySQL.
Neste guia você aprenderá:
- Como usar uma subconsulta correlacionada
- Como usar uma subconsulta correlacionada em um operador de comparação
- Como usar uma subconsulta como uma tabela derivada
Antes de começar
Para acompanhar este guia, certifique-se de ter o seguinte:
-
Se você ainda não o fez, crie uma conta Linode e Compute Instance. Veja nossos guias de Introdução ao Linode e Criação de uma instância de computação.
-
Siga nosso guia Configurando e protegendo uma instância de computação para atualizar seu sistema. Você também pode definir o fuso horário, configurar seu nome de host, criar uma conta de usuário limitada e proteger o acesso SSH.
-
O software do servidor MySQL (ou MariaDB) instalado no seu Linode. Consulte a seção MySQL, que contém guias que descrevem como instalar o MySQL em várias distribuições Linux.
Configurando o banco de dados
Para entender como as subconsultas funcionam, primeiro crie um banco de dados de exemplo. Este banco de dados de exemplo é usado para executar as diferentes consultas de exemplo neste guia:
-
SSH
ao seu servidor e faça login no MySQL como root:
mysql -u root -p
Quando solicitado, digite a senha root do seu servidor MySQL e pressione Enter continuar. Note que a senha root do seu servidor MySQL não é a mesma que a senha root do seu Linode.
Observação
Se sua senha não for aceita, talvez seja necessário executar o comando anterior comsudo
:
sudo mysql -u root -p
-
Se sua senha for aceita, você deverá ver o prompt do MySQL:
mysql >
Observação
Se você estiver usando o MariaDB, poderá ver um prompt como o seguinte:
MariaDB [(none)]>
-
Para criar um banco de dados de amostra chamadotest_db
, correr:
CREATE DATABASE test_db;
Você deve ver esta saída, que confirma que o banco de dados foi criado com sucesso:
Query OK, 1 row affected (0.01 sec)
-
Mude para otest_db
base de dados:
USE test_db;
Você deve ver esta saída:
Database changed
-
Você criou otest_db
e o selecionou. Em seguida, crie uma tabela chamadacustomers
:
CREATE TABLE customers ( customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;
Você deve ver esta saída:
Query OK, 0 rows affected (0.03 sec)
-
Adicione alguns registros aoscustomers
tabela. Execute oINSERT
abaixo comandos um por um:
INSERT INTO customers(customer_name) VALUES ('JOHN PAUL'); INSERT INTO customers(customer_name) VALUES ('PETER DOE'); INSERT INTO customers(customer_name) VALUES ('MARY DOE'); INSERT INTO customers(customer_name) VALUES ('CHRISTINE JAMES'); INSERT INTO customers(customer_name) VALUES ('MARK WELL'); INSERT INTO customers(customer_name) VALUES ('FRANK BRIAN');
Esta saída é mostrada após a inserção de cada registro:
Query OK, 1 row affected (0.00 sec) ...
-
Verifique se as informações dos clientes foram inseridas no banco de dados. Execute esteSELECT
comando:
SELECT * FROM customers;
Você deve ver esta lista de clientes:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 3 | MARY DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | | 6 | FRANK BRIAN | +-------------+-----------------+ 6 rows in set (0.00 sec)
-
Crie umasales
tabela. Esta tabela usa a colunacustomer_id
para referenciar oscustomers
tabela:
CREATE TABLE sales ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_id BIGINT, sales_amount DECIMAL(17,2) ) ENGINE = InnoDB;
Esta saída aparece:
Query OK, 0 rows affected (0.03 sec)
-
Em seguida, preencha assales
tabela com alguns registros. Execute oINSERT
abaixo comandos um por um:
INSERT INTO sales (customer_id, sales_amount) VALUES ('1','25.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','85.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','3.25'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','200.75'); INSERT INTO sales (customer_id, sales_amount) VALUES ('5','88.10'); INSERT INTO sales (customer_id, sales_amount) VALUES ('1','100.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('2','45.00'); INSERT INTO sales (customer_id, sales_amount) VALUES ('4','15.80');
Esta saída é mostrada após a inserção de cada registro:
Query OK, 1 row affected (0.01 sec) ...
-
Verifique os dados emsales
tabela. Execute esteSELECT
comando:
SELECT * FROM sales;
Esta lista de dados de vendas agora deve ser mostrada:
+----------+-------------+--------------+ | order_id | customer_id | sales_amount | +----------+-------------+--------------+ | 1 | 1 | 25.75 | | 2 | 2 | 85.25 | | 3 | 5 | 3.25 | | 4 | 4 | 200.75 | | 5 | 5 | 88.10 | | 6 | 1 | 100.00 | | 7 | 2 | 45.00 | | 8 | 4 | 15.80 | +----------+-------------+--------------+ 8 rows in set (0.00 sec)
Depois de configurar o banco de dados e as tabelas relacionadas, agora você pode implementar as diferentes subconsultas no MySQL.
Como usar uma subconsulta correlacionada
Uma subconsulta correlacionada é um tipo de consulta aninhada que usa os valores de uma consulta pai. Esses tipos de consultas fazem referência à consulta pai com uma coluna. A consulta aninhada é executada uma vez para cada linha na consulta pai.
O exemplo abaixo apresenta uma consulta que seleciona todos os clientes. Dentro da consulta, há uma subconsulta correlacionada que busca o valor total de vendas de cada cliente do
sales
tabela. -
Execute a consulta de exemplo:
SELECT customer_id, customer_name, (SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount FROM customers;
Neste exemplo, a subconsulta éSELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id
, que aparece entre parênteses.
Uma lista do total de vendas feitas pelos clientes é exibida:
+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | NULL | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | NULL | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
A saída acima da subconsulta correlacionada é capaz de fornecer uma lista resumida dos pedidos dos clientes. Observe, poiscustomer_id
s3
e6
não tem nenhum registro associado na tabela de vendas, seutotal_sales_amount
éNULL
.
-
Uma maneira mais elegante de apresentar esta lista é retornar0
em vez deNULL
para os clientes com vendas zero. Para fazer isso, coloque a saída gerada pela subconsulta com umIFNULL(expression, 0)
demonstração. Execute este comando atualizado:
SELECT customer_id, customer_name, IFNULL((SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id), 0) as total_sales_amount FROM customers;
A seguinte saída é exibida. MySQL retorna 0.00 para todas as linhas que teriam retornadoNULL
valores.
+-------------+-----------------+--------------------+ | customer_id | customer_name | total_sales_amount | +-------------+-----------------+--------------------+ | 1 | JOHN PAUL | 125.75 | | 2 | PETER DOE | 130.25 | | 3 | MARY DOE | 0.00 | | 4 | CHRISTINE JAMES | 216.55 | | 5 | MARK WELL | 91.35 | | 6 | FRANK BRIAN | 0.00 | +-------------+-----------------+--------------------+ 6 rows in set (0.00 sec)
Essa abordagem ajuda a garantir que a saída não prejudique nenhum cálculo adicional nos registros.
Como usar uma subconsulta correlacionada em um operador de comparação
As subconsultas são úteis para mover a lógica de negócios para o nível de consulta do banco de dados. Os seguintes casos de uso de negócios apresentam subconsultas correlacionadas colocadas dentro da cláusula WHERE de uma consulta pai:
-
Considere um cenário em que você gostaria de obter uma lista de todos os clientes cadastrados no banco de dados que não possuem vendas associadas. Você pode usar uma subconsulta junto com o operador de comparação MySQLNOT IN
e recuperar estes clientes:
SELECT customer_id, customer_name FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
Neste exemplo, a subconsulta éSELECT customer_id FROM sales
, que aparece entre parênteses. O comando SQL acima gera uma lista de dois clientes que não são encontrados na tabela de vendas:
+-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 3 | MARY DOE | | 6 | FRANK BRIAN | +-------------+---------------+ 2 rows in set (0.00 sec)
Em um ambiente de produção, você pode usar esse tipo de conjunto de registros para tomar melhores decisões de negócios. Por exemplo, você pode criar um script usando outra linguagem como PHP ou Python para enviar um e-mail a esses clientes e perguntar se eles têm algum problema ao fazer um pedido.
-
Outro caso de uso é na limpeza de dados. Por exemplo, você pode usar uma subconsulta para excluir clientes que nunca fizeram um pedido:
DELETE FROM customers WHERE customer_id NOT IN (SELECT customer_id FROM sales);
O comando SQL acima exclui os dois clientes e gera o seguinte:
Query OK, 2 rows affected (0.01 sec)
Se você executar um comando para listar todos os clientes novamente, esses clientes não deverão mais aparecer na tabela:
SELECT * FROM customers;
A saída abaixo confirma que os clientes sem pedidos associados foram excluídos:
+-------------+-----------------+ | customer_id | customer_name | +-------------+-----------------+ | 1 | JOHN PAUL | | 2 | PETER DOE | | 4 | CHRISTINE JAMES | | 5 | MARK WELL | +-------------+-----------------+ 4 rows in set (0.00 sec)
Como usar uma subconsulta como uma tabela derivada
Quando as subconsultas são usadas no
FROM
cláusula de uma consulta pai, eles são chamados de tabelas derivadas . Eles são muito importantes ao implementar consultas complexas que, de outra forma, exigiriam um MySQL VIEW
, JOIN
, ou UNION
cláusula. Uma tabela derivada existe na consulta que a criou e não é salva permanentemente no banco de dados. Quando as subconsultas são usadas como tabelas derivadas, elas isolam as diferentes partes da instrução SQL. Em outras palavras, a subconsulta fornece uma expressão simplificada de uma tabela que pode ser usada no escopo da consulta pai.
Observação Lembre-se, toda tabela derivada deve ter um alias.
Execute o comando abaixo para criar uma subconsulta de tabela derivada com alias como
order_summary
:SELECT customer_id
FROM
(
SELECT
customer_id,
count(order_id) as total_orders
FROM sales
group by customer_id
) as order_summary
WHERE order_summary.total_orders > 1;
Observação
Neste comando, a subconsulta aparece entre parênteses como:
SELECT customer_id, count(order_id) as total_orders FROM sales group by customer_id
O comando acima consulta a tabela de vendas para determinar os clientes com mais de 1 pedido. Quando você executa a consulta, esta saída é exibida:
+-------------+
| customer_id |
+-------------+
| 1 |
| 2 |
| 5 |
| 4 |
+-------------+
4 rows in set (0.00 sec)
A lista acima mostra quatro
customer_id
s que têm mais de um pedido. Como exemplo de caso de uso de negócios, você pode usar essa consulta em um script que recompensa os clientes com um bônus em sua próxima compra. Mais informações
Você pode querer consultar os seguintes recursos para obter informações adicionais sobre este tópico. Embora estes sejam fornecidos na esperança de que sejam úteis, observe que não podemos garantir a precisão ou pontualidade dos materiais hospedados externamente.
- Subconsultas do MySQL