Considere o script SQL a seguir. CREATE TABLE processo ( id_processo SERIAL PRIMARY KEY, ano INTEGER NOT NULL ); CREATE TABLE audiencia ( id_audiencia SERIAL PRIMARY KEY, id_processo INTEGER NOT NULL REFERENCES processo(id_processo), duracao_minutos INTEGER NOT NULL); INSERT INTO processo (id_processo, ano) VALUES (1, 2023), (2, 2023), (3, 2024), (4, 2024); INSERT INTO audiencia (id_processo, duracao_minutos) VALUES (1, 50), (1, 80), (2, 120), (3, 40); Para listar o ano e a média da duração das audiências, exibindo somente os anos cuja soma das durações ultrapasse 100 minutos, deve-se utilizar a query:
ASELECT p.ano, AVG(a.duracao_minutos) FROM processo p LEFT JOIN audiencia a ON p.id_processo = a.id_processo GROUP BY p.ano HAVING AVG(a.duracao_minutos) > 100;
BSELECT p.ano, AVG(a.duracao_minutos) FROM processo p INNER JOIN audiencia a ON p.id_processo = a.id_processo GROUP BY p.ano HAVING SUM(a.duracao_minutos) > 100;
CSELECT ano, AVG(duracao_minutos) FROM processo p LEFT JOIN audiencia a USING (id_processo) GROUP BY ano HAVING COUNT(a.id_processo) > 100;
DSELECT p.ano, AVG(a.duracao_minutos) FROM audiencia a RIGHT JOIN processo p ON a.id_processo = p.id_processo GROUP BY p.ano HAVING SUM(a.duracao_minutos) IS NULL;
ESELECT ano, AVG(duracao_minutos) FROM audiencia a JOIN processo p USING (id_processo) GROUP BY ano HAVING SUM(duracao_minutos) = MAX(duracao_minutos);
Revelar gabarito e comentário▾
GabaritoB — SELECT p.ano, AVG(a.duracao_minutos)
FROM processo p
INNER JOIN audiencia a ON p.id_processo =
a.id_processo
GROUP BY p.ano
HAVING SUM(a.duracao_minutos) > 100;
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”.
Consulta SQL com GROUP BY e HAVING: Filtro sobre Agregação
Gabarito: letra B. A consulta correta usa INNER JOIN para combinar apenas os processos que possuem audiências, GROUP BY p.ano para agrupar por ano, e HAVING SUM(a.duracao_minutos) > 100 para filtrar os grupos cuja soma das durações ultrapassa 100 minutos — exatamente o que o enunciado pede. A pegadinha central está em trocar SUM por AVG no HAVING, como faz a alternativa A.
O comando SQL é executado em uma ordem lógica que não corresponde à ordem em que escrevemos as cláusulas. Primeiro, o banco identifica as tabelas e aplica os joins (FROM/JOIN), depois filtra linhas individuais (WHERE), em seguida agrupa (GROUP BY), calcula as funções de agregação (SUM, AVG, COUNT), filtra os grupos com HAVING, e só então projeta as colunas (SELECT) e ordena (ORDER BY). Essa sequência é a chave para entender por que o HAVING pode usar SUM e AVG, enquanto o WHERE não pode — o WHERE roda antes da agregação, então não enxerga os totais.
No problema, temos duas tabelas: processo (com id_processo e ano) e audiencia (com id_audiencia, id_processo e duracao_minutos). A consulta deve listar o ano e a média da duração das audiências, mas somente para os anos cuja soma das durações ultrapasse 100 minutos. Vamos calcular os dados para verificar:
Ano 2023: processos 1 e 2. Audiências: processo 1 (50 e 80) e processo 2 (120). Soma = 50 + 80 + 120 = 250 minutos. Média = 250 / 3 ≈ 83,33 minutos.
Ano 2024: processos 3 e 4. Audiências: processo 3 (40). Processo 4 não tem audiência. Soma = 40 minutos. Média = 40 / 1 = 40 minutos.
Portanto, apenas o ano 2023 deve aparecer no resultado, pois sua soma (250) ultrapassa 100, enquanto a soma de 2024 (40) não. A alternativa B produz exatamente isso: o INNER JOIN descarta o processo 4 (sem audiência), agrupa por ano, calcula a média e filtra com HAVING SUM > 100.
A distinção crucial é entre WHERE e HAVING: o WHERE filtra linhas antes da agregação, enquanto o HAVING filtra grupos depois da agregação. Como o critério é sobre a soma das durações (um valor agregado), o filtro só pode ser feito no HAVING. Além disso, o INNER JOIN é o correto porque só queremos anos que tenham audiências — se usássemos LEFT JOIN, o ano 2024 entraria com NULL para a duração, e a média seria calculada apenas sobre as linhas não nulas, mas a soma seria 40, então ainda seria filtrado. No entanto, o INNER JOIN é semanticamente mais preciso.
A banca explora a confusão entre SUM e AVG no HAVING. O enunciado pede explicitamente "anos cuja soma das durações ultrapasse 100 minutos", então o filtro deve ser SUM(a.duracao_minutos) > 100. A alternativa A usa AVG no HAVING, o que filtraria anos com média acima de 100 — nenhum ano tem média acima de 100 (2023 tem ~83, 2024 tem 40), então retornaria vazio. Essa é a armadilha clássica: trocar a função de agregação no filtro de grupo.
Guarde a fronteira entre WHERE (filtro de linha) e HAVING (filtro de grupo), e entre SUM (soma) e AVG (média): é exatamente nesses pares que as alternativas se dividem.
1FROM/JOIN
2WHERE
3GROUP BY
4Agregações (SUM/AVG)
5HAVING
6SELECT
7ORDER BY
LEVEL · soulevel.com.br
Alternativa A — ❌ Incorreta
Usa HAVING AVG(a.duracao_minutos) > 100, mas o enunciado pede que a soma ultrapasse 100 minutos. A média do ano 2023 é ~83,33, e a de 2024 é 40 — nenhuma ultrapassa 100, então a consulta retornaria um conjunto vazio. O erro é trocar SUM por AVG no filtro de grupo.
Alternativa B — ✅ Correta ⟵ GABARITO
Usa INNER JOIN para combinar apenas processos com audiências, GROUP BY p.ano para agrupar, AVG(a.duracao_minutos) para calcular a média e HAVING SUM(a.duracao_minutos) > 100 para filtrar os anos cuja soma ultrapassa 100. Com os dados, retorna apenas o ano 2023 com média ~83,33, exatamente como pedido.
Alternativa C — ❌ Incorreta
Usa HAVING COUNT(a.id_processo) > 100, que conta o número de audiências por ano, não a soma das durações. Nenhum ano tem mais de 100 audiências (2023 tem 3, 2024 tem 1), então retornaria vazio. O erro é usar COUNT em vez de SUM.
Alternativa D — ❌ Incorreta
Usa HAVING SUM(a.duracao_minutos) IS NULL, que filtra grupos onde a soma é nula — ou seja, anos sem audiências. Isso retornaria o ano 2024 (que não tem audiência), mas o enunciado pede anos cuja soma ultrapasse 100, não anos sem audiências. Além disso, o RIGHT JOIN inclui processos sem audiência, o que é o oposto do desejado.
Alternativa E — ❌ Incorreta
Usa HAVING SUM(duracao_minutos) = MAX(duracao_minutos), que filtra grupos onde a soma é igual à duração máxima — ou seja, anos com apenas uma audiência. Isso retornaria o ano 2024 (soma = 40, max = 40), mas o enunciado pede anos cuja soma ultrapasse 100. O erro é usar uma condição sem relação com o critério pedido.
A regra de ouro para questões de GROUP BY/HAVING: leia atentamente se o filtro é sobre a soma, a média, a contagem ou outro agregado, e use a função correspondente no HAVING. O WHERE nunca pode filtrar agregados, e o HAVING nunca pode filtrar linhas individuais.