Consultas de Agrupamento
Em determinadas situações o usuário pode desejar fazer consultas no banco de dados de forma agrupada. Essa forma de consulta permite ao usuário visualizar as informações dos registros de forma mais geral, possibilitando que o mesmo capture informações resumidas, porém de grande importância, do sistema.
Por meio das consultas de agrupamento, o usuário pode, por exemplo:
- Descobrir a média de vendas de seus funcionários no mês
- Visualizar o total de vendas em cada semana da sua loja
- Visualizar quantos usuários pertencem a um determinado grupo
- Descobrir quais alunos passaram em uma determinada disciplina
- Verificar quantas tarefas cada usuário possui em aberto
A consulta por agrupamento é feita por meio de um comando SELECT, porém adicionado da cláusula GROUP BY. O trecho de código abaixo descreve a sintaxe básica da cláusula GROUP BY:
SELECT campo1, FUNCAO(campo2), ...
...
GROUP BY campo1
O parâmetro campo1 representa o campo no qual a cláusula GROUP BY irá agrupar os registros resultantes do SELECT. É possível fazer consultas que agrupem por um ou mais campos, a depender das necessidades do usuário. O parâmetro FUNCAO(campo2) representa uma função agregadora, que irá agrupar todos os valores de campo2 de acordo com o valor de campo1.
É importante ressaltar que o uso de uma função agregadora é obrigatória para consultas de agrupamento. Pois caso não seja fornecida, o SGBD não saberá como ele irá agrupar os registros que tem o mesmo valor para o campo de agrupamento, porém valores distintos para os demais grupos. O trecho de código abaixo mostra alguns exemplos de utilização:
/* busca pelo número de tarefas de cada usuário */
SELECT usuarios.nome, COUNT(tarefas.id)
FROM usuarios
JOIN tarefas ON tarefas.usuario_id = usuarios.id
GROUP BY usuarios.nome;
/* busca pelo número de tarefas abertas por categoria */
SELECT tarefas.categoria_id, COUNT(tarefas.id)
FROM tarefas
WHERE tarefas.data_limite > NOW()
GROUP BY tarefas.categoria_id;
/* busca pela quantidade de tarefas abertas por categoria para cada usuário */
SELECT usuarios.nome, categorias.nome, COUNT(tarefas.id)
FROM usuarios
JOIN tarefas ON tarefas.usuario_id = usuarios.id
JOIN categorias ON tarefas.categoria_id = categorias.id
WHERE tarefas.data_limite > NOW()
GROUP BY usuarios.nome, categorias.nome
A Cláusula HAVING
Como podemos observar, a execução do GROUP BY acontece após a filtragem realizada pelo WHERE. Em outras palavras, não é possível fazer filtragens dos valores de agrupamento diretamente na cláusula WHERE. Para isso, a linguagem SQL disponibilizou um comando específico para filtragem de valores resultantes de uma função de agregação: a cláusula HAVING. O trecho de código abaixo descreve a sintaxe básica de utilização da filtragem por meio do HAVING:
SELECT campo1, FUNCAO(campo2), ...
...
GROUP BY campo1
HAVING restricao;
Como podemos observar, a declaração da cláusula HAVING deve vir após o GROUP BY. Ainda, o parâmetro restricao deve contemplar restrições que fazem o filtro com base no valor resultante da função agregadora. O trecho de código abaixo mostra como ficaria algumas das consultas descritas anteriormente com a implementação da cláusula HAVING:
/* busca por usuários que tem pelo menos uma tarefas em aberto */
SELECT usuarios.nome
FROM usuarios
JOIN tarefas ON tarefas.usuario_id = usuarios.id
GROUP BY usuarios.nome
HAVING COUNT(tarefas.id) > 0;
/* busca por categorias que tem pelo menos 5 tarefas */
SELECT tarefas.categoria_id, COUNT(tarefas.id)
FROM tarefas
WHERE tarefas.data_limite > NOW()
GROUP BY tarefas.categoria_id
HAVING COUNT(tarefas.id) >= 5;