As tabelas contribuinte e pagamento apresentadas anteriormente fazem parte do banco de dados da secretaria de fazenda de certo ente federativo. A administração tributária deste ente deseja listar os nomes dos contribuintes cujo valor total de pagamentos é superior à média total dos pagamentos de todos os contribuintes.
A partir dessa situação hipotética, assinale a opção em que é corretamente apresentada a instrução adequada, de acordo com o padrão SQL/ANSI, para se obter a lista desejada pela administração tributária.
ASELECT c.nome, SUM(p.valor) FROM contribuinte c JOIN pagamento p USING (id_contribuinte) HAVING SUM(p.valor) > ALL (SELECT AVG(valor) FROM pagamento)
BSELECT c.nome, SUM(p.valor) AS total FROM contribuinte c JOIN pagamento p ON c.id_contribuinte = p.id_contribuinte GROUP BY c.nome HAVING SUM(p.valor) > (SELECT AVG(valor) FROM pagamento)
CSELECT c.nome, p.valor FROM contribuinte c JOIN pagamento p ON c.id_contribuinte = p.id_contribuinte HAVING p.valor > AVG(valor)
DSELECT c.nome, SUM(p.valor) AS total FROM contribuinte c JOIN pagamento p ON c.id_contribuinte = p.id_contribuinte WHERE SUM(p.valor) > (SELECT AVG(valor) FROM pagamento) GROUP BY c.nome
ESELECT c.nome, SUM(p.valor) AS total FROM contribuinte c LEFT JOIN pagamento p ON c.id_contribuinte = p.id_contribuinte GROUP BY c.nome WHERE SUM(p.valor) > (SELECT AVG(valor) FROM pagamento)
Revelar gabarito e comentário▾
GabaritoB — SELECT c.nome, SUM(p.valor) AS total
FROM contribuinte c JOIN pagamento p
ON c.id_contribuinte = p.id_contribuinte
GROUP BY c.nome
HAVING SUM(p.valor) > (SELECT AVG(valor) FROM
pagamento)
Comentário gerado por IA. É um apoio ao estudo, ancorado em fontes, mas pode conter imprecisões — confira sempre na fonte oficial (lei, súmula, edital e gabarito da banca). Encontrou um erro? Use “Reportar”.
SQL – Agregação com GROUP BY e HAVING para Comparação com Média
Gabarito: letra B. A consulta correta agrupa os pagamentos por contribuinte, calcula o total de cada um com SUM(p.valor) e filtra os grupos cujo total supera a média geral de pagamentos, usando HAVING com uma subconsulta (SELECT AVG(valor) FROM pagamento). A cláusula HAVING é a única que pode filtrar resultados de funções de agregação, e a subconsulta calcula a média de todos os pagamentos, exatamente como pede o enunciado.
O problema pede uma consulta que compare o total pago por cada contribuinte com a média geral de todos os pagamentos. Para isso, precisamos de duas operações distintas: agregar os valores por contribuinte e comparar o resultado com um valor calculado sobre toda a tabela. A função SUM soma os valores de um grupo, e a função AVG calcula a média. A cláusula GROUP BY define os grupos (no caso, por nome do contribuinte), e a cláusula HAVING filtra esses grupos com base em uma condição que envolve uma função de agregação. A subconsulta (SELECT AVG(valor) FROM pagamento) retorna a média de todos os pagamentos, que é um valor escalar. A comparação SUM(p.valor) > (SELECT AVG(valor) FROM pagamento) é, portanto, válida e atende exatamente ao requisito.
A pegadinha central desta questão está na distinção entre WHERE e HAVING. O WHERE filtra linhas individuais antes do agrupamento, e por isso não pode usar funções de agregação. O HAVING filtra grupos após o agrupamento, e é o único lugar onde SUM, AVG, COUNT etc. podem aparecer na condição de filtro. Além disso, a subconsulta deve ser usada para calcular a média geral, pois não é possível usar AVG(valor) diretamente no HAVING sem uma subconsulta, já que isso se referiria à média de cada grupo, não à média geral. A alternativa correta combina GROUP BY c.nome com HAVING SUM(p.valor) > (SELECT AVG(valor) FROM pagamento), que é a estrutura canônica para esse tipo de comparação.
Vamos analisar cada alternativa em detalhe, identificando o erro específico de cada uma.
1JOIN contribuinte × pagamento
2GROUP BY c.nome
3SUM(p.valor) por grupo
4HAVING > subconsulta AVG
LEVEL · soulevel.com.br
Alternativa A — ❌ Incorreta
O erro está no uso de HAVING sem GROUP BY. A cláusula HAVING só pode ser usada após um GROUP BY para filtrar grupos. Sem GROUP BY, a consulta trata toda a tabela como um único grupo, e a função SUM(p.valor) agregaria todos os pagamentos, não por contribuinte. Além disso, > ALL (SELECT AVG(valor) FROM pagamento) compara o total com a média de cada pagamento individual, o que não é o que se pede. A sintaxe USING (id_contribuinte) é válida, mas a falta de GROUP BY torna a consulta semanticamente incorreta para o objetivo.
Alternativa B — ✅ Correta ⟵ GABARITO
Esta é a instrução correta. Ela faz o JOIN entre contribuinte e pagamento usando ON c.id_contribuinte = p.id_contribuinte, agrupa os resultados por c.nome com GROUP BY c.nome, calcula o total de pagamentos de cada contribuinte com SUM(p.valor) AS total, e filtra os grupos com HAVING SUM(p.valor) > (SELECT AVG(valor) FROM pagamento). A subconsulta (SELECT AVG(valor) FROM pagamento) retorna a média de todos os pagamentos, e a comparação é feita corretamente. A ordem das cláusulas está correta: SELECT, FROM, JOIN, GROUP BY, HAVING.
Alternativa C — ❌ Incorreta
Esta alternativa tem dois erros graves. Primeiro, não há GROUP BY, então SUM(p.valor) não pode ser usado no SELECT sem agrupar. Segundo, a condição HAVING p.valor > AVG(valor) é inválida: p.valor é uma coluna individual, não uma agregação, e AVG(valor) sem GROUP BY não faz sentido no HAVING. Além disso, a consulta não calcula o total por contribuinte, apenas seleciona valores individuais.
Alternativa D — ❌ Incorreta
O erro está no uso de WHERE SUM(p.valor) > (SELECT AVG(valor) FROM pagamento). A cláusula WHERE não pode conter funções de agregação como SUM, pois ela filtra linhas antes do agrupamento. A condição correta deveria estar no HAVING, após o GROUP BY. A ordem das cláusulas também está errada: WHERE deve vir antes de GROUP BY, não depois.
Alternativa E — ❌ Incorreta
Esta alternativa tem dois erros. Primeiro, a ordem das cláusulas está incorreta: WHERE deve vir antes de GROUP BY, mas aqui aparece depois. Segundo, o uso de WHERE SUM(p.valor) > (SELECT AVG(valor) FROM pagamento) é inválido, pois WHERE não pode usar funções de agregação. A condição deveria estar no HAVING. Além disso, o LEFT JOIN não é necessário para o objetivo, pois a consulta deve listar apenas contribuintes que têm pagamentos (a condição SUM(p.valor) > média já exclui contribuintes sem pagamentos, pois SUM seria NULL).