Apesar da maioria das consultas feitas por quem está começando em SQL ser com SELECT externos, nesse artigo vou apresentar um recurso bastante útil que vai ajudar você a melhorar a legibilidade da sua query assim como, em alguns casos, otimizar o tempo do retorno das suas informações para o usuário. As chamadas subconsultas.
Uma subconsulta nada mais é do que uma instrução SELECT dentro de outro SELECT que retorna algumas colunas específicas que são usadas em algumas funções como INSERT e UPDATE por exemplo.
1. Tipos de subconsultas
Segue abaixo os tipos de subconsultas:
- Subconsultas de uma única linha: retornam zero ou uma linha para a instrução SQL externa;
- Subconsultas de várias linhas: retornam uma ou mais linhas para a SQL externa;
- Subconsultas de várias colunas: retornam mais de uma coluna para a instrução SQL externa;
- Subconsultas correlacionadas: fazem referência a uma ou mais colunas na instrução SQL externa;
- Subconsultas aninhadas: são feitas dentro de outra subconsulta (podemos aninhar até 255 subconsultas).
Nesse artigo, darei uma pequena introdução e explicarei o primeiro tipo com vários exemplos e explicações. Depois, em outro artigo, tratarei do restante e aprofundaremos mais no assunto.
2. Subconsultas de uma única linha
Como já mencionado, uma subconsulta de uma única linha é aquela que retorna zero ou uma linha para a instrução SQL externa. Podemos colocar subconsultas em diversas expressões utilizando WHERE, HAVING ou em uma cláusula FROM.
2.1 Subconsultas em uma cláusula WHERE
Abaixo, segue um exemplo de subconsulta numa cláusula WHERE:
SELECT first_name, last_name FROM customers WHERE customer_id = (SELECT customer_id FROM customers WHERE last_name = 'Brown');
Resultando em:
Esse exemplo recupera os valores de first_name e last_name da linha da tabela customers onde o valor de last_name é Brown. O valor de customer_id para essa linha é 1, o qual é passado para a cláusula WHERE da consulta externa.
Além disso, podemos usar outros operadores de uma única linha, ou seja, na consulta anterior usamos o operador de igualdade (=). Podemos também usar outros operadores de comparação em subconsultas de uma única linha.
O exemplo abaixo usa o operador ‘>’:
SELECT product_id, name, price FROM products WHERE price > (SELECT AVG(price) FROM products)
Resultando em:
A subconsulta usa a função avg() para obter o preço médio dos produtos, onde é passado para a cláusula WHERE da consulta externa.
2.2 Subconsultas em uma cláusula HAVING
Podemos colocar uma subconsulta na cláusula HAVING de uma consulta externa. Isso nos permite filtrar grupos de linhas com base no resultado retornado pela subconsulta.
O exemplo abaixo recupera o valor de product_type_id e o preço médio dos produtos cujo preço médio é menor do que o máximo da média dos grupos do mesmo tipo de produto. Analisemos:
SELECT product_type_id, AVG(price) FROM products GROUP BY product_type_id HAVING AVG(price) < (SELECT MAX(AVG(price)) FROM products GROUP BY product_type_id) ORDER BY product_type_id;
Resultando em:
Aqui podemos observar que a subconsulta usa AVG() para calcular o primeiro preço médio, assim o resultado disso é retornado para MAX(), que retorna o máximo das médias.
Se analisarmos consulta por consulta, seria assim:
- SELECT MAX(AVG(price)) FROM products GROUP BY product_type_id: retorna a maior média dentre os grupos de id fornecidos no filtro. No caso, 26,22.
- SELECT product_type_id, AVG(price) FROM products
GROUP BY product_type_id ORDER BY product_type_id: retorna os grupos com valor de product_type_id iguai a 1, 3, 4 e nulo têm o preço médio menor que 26.22, assim como esperado.
2.3 Subconsultas em uma cláusula FROM
Os tipos de subconsultas colocadas em uma cláusula FROM também são chamadas de visões inline.
Exemplo: SELECT product_id FROM (SELECT product_id FROM products WHERE product_id < 3);
Resultando em:
No que diz respeito à cláusula FROM da consulta externa, a saída da subconsulta é apenas uma fonte de dados.
Analisemos a consulta a seguir:
SELECT p.product_id, price, purchases_data.product_count FROM products p, (SELECT product_id, COUNT (product_id) product_count FROM purchases GROUP BY product_id) purchases_data WHERE p.product_id = purchases_data.product_id;
Temos como resultado:
Notemos que a subconsulta recupera os valores de product_id e count(product_id) da tabela purchases e os retorna para a consulta externa. A saída da subconsulta é somente outra fonte de dados para a cláusula FROM da consulta externa.
As subconsultas são altamente importantes para aqueles que desejam criar consultas bem elaboradas, legíveis e otimizadas. No próximo artigo, iremos ver os demais tipos de subconsultas e como elas podem nos ajudar a escrever queries bem feitas e com baixo custo de tempo.