segunda-feira, 16 de novembro de 2015

SQL: Subqueries

Olá pessoal, hoje falaremos sobre Subqueries, que nada mais são que queries dentro de queries, ou seja, consultas dentro de consultas.

Quando utilizar subqueries?

Você utiliza uma subquerie, quando a sua query principal precisa de uma informação que ela sozinha não é capaz de obter. Por exemplo, imagine que exista a tabela de funcionários, e nela existem os campos: id_funcionario, nome, cargo e salario. Você deseja montar uma query para recuperar todos os funcionários programadores. Para isso, você utiliza a query:

SELECT nome FROM funcionarios WHERE cargo = 'Programador';

Agora, e se você quiser saber qual é o programador que ganha mais?

Perceba que neste caso, temos duas perguntas: 'Qual o maior salário dentre os programadores' e 'quem é esse programador'.

Bem, a segunda pergunta já foi respondida com o comando SQL acima.
Para saber qual o maior salario pago a um programador, podemos utilizar a seguinte query:

SELECT MAX(salario) FROM funcionarios WHERE cargo = 'Programador';

No comando acima, utilizamos a função MAX. O objetivo dela é identificar qual o maior valor dentre os registros da coluna informada. A SQL acima retornará apenas o valor numérico do maior salário.

Para completar a nossa consulta, devemos unir estas duas queries, onde, a consulta entre parênteses  é chamada de subconsulta ou consulta interna:

SELECT nome FROM funcionarios WHERE salario = (SELECT MAX(salario) FROM funcionarios WHERE cargo = 'Programador');

Como dito anteriormente, a query que está entre parênteses (subquey) retorna apenas um valor. A este valor podemos chamar de valor escalar (uma linha, uma coluna), que pode ser usado em uma operação de comparação como o WHERE, ou até em operações matemáticas, caso estajamos lidando com números.

Uma subconsulta é sempre um comando SELECT. Então como vimos acima, tinhamos duas perguntas e dois comandos SELECT. O comando SELECT da subconsulta deve projetar apenas uma coluna, a menos que estejamos trabalhando com o comando EXISTS (falaremos sobre ele mais tarde).

Tendo compreendido o funcionamento básico de uma subquerie, imagine que além da tabela 'funcionários', a empresa mantenha uma outra tabela chamada 'gratificacao'. Esta tabela registra o funcionario, o prêmio recebido, e a data.

Nesta nova pesquisa, desejaremos obter todos os funcionarios que já receberam algum tipo de gratificação na empresa. Pra isso, temos duas perguntas a responder:

1 - Quem são os funcionários da empresa?
            SELECT nome FROM funcionarios;

2 - Quais já receberam gratificação?
            SELECT id_funcionario FROM gratificacao;

Perceba que a resposta para a segunda pergunta não retorna um valor escalar. Será retornado uma lista com o id dos usuários que estão na tabela 'gratificação', ou seja, os usuários que já receberam algum prêmio.
Perceba também que nós continuamos projetando apenas 1 coluna na query. Estamos buscando uma lista de valores, mas para apenas 1 coluna.

Transformando em uma única query obtemos o seguinte:

SELECT * FROM funcionarios WHERE id_funcionario IN (SELECT id_funcionario FROM gratificacao);

Consegue ver algo de diferente nesta query?
Isto mesmo, estamos usando o comando IN que compara dentre uma lista de valores.

Traduzindo esta query para a nossa linguagem, temos:

Traga TODOS os registros da tabela FUNCIONÁRIO onde o id do funcionário esteja nesta lista: 3, 5, 1, 4 (lista dos que receberam a gratificação)

Simples não?

O mesmo pode ser feito com o comando NOT IN, que é apenas o contrario do que fizemos acima. Ele vai buscar os funcionários que NÃO estão na lista.

Funcionários que não receberam a gratificação:
SELECT * FROM funcionarios WHERE id_funcionario NOT IN (SELECT id_funcionario FROM gratificacao);

Por ultimo e não menos importante, temos o comando EXISTS.
O Comando EXISTS é mais flexível que o IN, pois ele permite que os seus resultados sejam melhor elaborados, com mais possibilidades de filtragem.
O EXISTS não se importa com o que você está projetando na consulta interna, ou seja, ele não está nem aí para os campos que você usa com o SELECT. Ele só se importa com a condição que você definiu na consulta interna para que os dados na consulta externa sejam exibidos.

A Query abaixo, com o comando EXISTS, produz a mesma saída que fizemos com o comando IN, mas ele te dá muito mais liberdade na hora de criar as condições para a pesquisa dos dados.


SELECT * FROM funcionarios f WHERE EXISTS (SELECT * FROM gratificacao g WHERE f.id_funcionario = g.id_funcionario);

Nenhum comentário:

Postar um comentário