Questão de Banco de Dados — SQL — CESPE / CEBRASPE 2024
Banco de Dados›SQL
Código
ce173494
Banca
CESPE / CEBRASPE
Órgão
FINEP
Ano
2024
Nível
Superior
Cargo
Analista - Tecnologia da Informação - Infraestrutura
Na tabela SQL criada pela expressão a seguir, sessao corresponde a uma sessão e a variável duracao corresponde à duração da sessão de certo usuário.A partir dessas informações, assinale a opção que corresponde ao script utilizado para se obter o tempo médio de duração das sessões dos usuários que tenham mais de uma sessão.
A
B
C
D
E
Revelar gabarito e comentário▾
GabaritoA — [imagem]
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: agrupamento e filtro de grupos com GROUP BY e HAVING
Gabarito: letra A. Para obter o tempo médio de duração das sessões dos usuários que tenham mais de uma sessão, o script correto é SELECT userid, avg(duracao) FROM sessao GROUP BY userid HAVING count(*) > 1. A consulta agrupa as sessões por usuário, calcula a média da duração em cada grupo e, com a cláusula HAVING, filtra apenas os grupos que possuem mais de uma sessão — exatamente o que o enunciado pede.
A questão cobra dois conceitos centrais da linguagem SQL que costumam andar juntos: a função de agregação AVG e as cláusulas GROUP BY e HAVING. Vamos entender cada um deles com calma, porque é aí que mora a diferença entre acertar e errar.
O que é uma função de agregação? Funções de agregação (ou funções agregadas) são funções que operam sobre um conjunto de linhas e retornam um único valor resumido. As mais comuns são COUNT (conta linhas), SUM (soma valores), AVG (calcula a média aritmética), MIN (menor valor) e MAX (maior valor). No nosso caso, AVG(duracao) calcula a média aritmética dos valores da coluna duracao dentro de cada grupo.
O que faz o GROUP BY? A cláusula GROUP BY agrupa linhas que têm os mesmos valores em uma ou mais colunas. No nosso caso, GROUP BY userid agrupa todas as sessões de um mesmo usuário em um único grupo. É como se o banco "juntasse" todas as linhas de cada usuário e, para cada grupo, aplicasse as funções de agregação. Sem o GROUP BY, a função AVG seria aplicada a todas as linhas da tabela de uma vez, retornando uma única média geral — o que não atende ao pedido, pois queremos a média por usuário.
Qual a diferença entre WHERE e HAVING? Essa é a pegadinha clássica da banca. A cláusula WHERE filtra linhas individuais antes do agrupamento. A cláusula HAVING filtra grupos depois do agrupamento. No nosso caso, queremos filtrar grupos de usuários que tenham mais de uma sessão. O número de sessões de um usuário só é conhecido depois de agrupar e contar — por isso, o filtro precisa ser feito com HAVING, e não com WHERE. Usar WHERE count(*) > 1 é um erro de sintaxe, pois WHERE não aceita funções de agregação.
Vamos ver um exemplo concreto. Suponha a tabela sessao:
id
userid
duracao
1
10
30
2
10
50
3
20
40
4
30
60
5
30
20
6
30
10
A consulta SELECT userid, avg(duracao) FROM sessao GROUP BY userid HAVING count(*) > 1 funciona assim:
Agrupa por userid: grupo do usuário 10 (linhas 1 e 2), grupo do usuário 20 (linha 3), grupo do usuário 30 (linhas 4, 5 e 6).
Calculaavg(duracao) para cada grupo: usuário 10 → (30+50)/2 = 40; usuário 20 → 40; usuário 30 → (60+20+10)/3 = 30.
Filtra com HAVING count(*) > 1: usuário 10 (2 sessões) e usuário 30 (3 sessões) passam; usuário 20 (1 sessão) é descartado.
Retorna: usuário 10 com média 40 e usuário 30 com média 30.
A ordem lógica de execução de uma consulta SQL é: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Isso explica por que o HAVING consegue usar funções de agregação (ele roda depois do agrupamento) e o WHERE não (ele roda antes).
Guarde essa fronteira: WHERE filtra linhas, HAVING filtra grupos. É exatamente nela que as alternativas desta questão se dividem.
1FROM
2WHERE
3GROUP BY
4HAVING
5SELECT
6ORDER BY
LEVEL · soulevel.com.br
Alternativa A — ✅ Correta ⟵ GABARITO
O script SELECT userid, avg(duracao) FROM sessao GROUP BY userid HAVING count(*) > 1 está sintaticamente correto e semanticamente perfeito para o que se pede. Ele agrupa as sessões por usuário (GROUP BY userid), calcula a média de duração de cada grupo (avg(duracao)) e filtra apenas os grupos com mais de uma sessão (HAVING count(*) > 1). A combinação GROUP BY + HAVING é a forma canônica de responder a perguntas que envolvem "usuários que tenham mais de uma sessão" ou qualquer condição sobre o grupo.
Alternativa B — ❌ Incorreta
O script SELECT id, userid, avg(duracao) FROM sessao WHERE count(*) > 1 apresenta dois erros graves. Primeiro, a cláusula WHERE não aceita funções de agregação como count(*) — ela filtra linhas individuais antes do agrupamento, e o número de sessões de um usuário só é conhecido depois de agrupar. Segundo, a coluna id não está no GROUP BY (que nem existe aqui), o que viola a regra de que toda coluna no SELECT que não esteja em uma função de agregação deve aparecer no GROUP BY. O correto seria usar HAVING count(*) > 1 e agrupar por userid.
Alternativa C — ❌ Incorreta
Sem o texto literal da alternativa C no enunciado, não é possível apontar o erro específico. No entanto, pelo padrão da banca, é provável que ela troque HAVING por WHERE (erro de sintaxe) ou que esqueça o GROUP BY, o que faria a consulta retornar uma única média geral em vez da média por usuário. O método de resolução é o mesmo: verificar se a consulta agrupa por userid, usa avg(duracao) e filtra com HAVING count(*) > 1.
Alternativa D — ❌ Incorreta
Sem o texto literal da alternativa D no enunciado, não é possível apontar o erro específico. Pelo padrão da banca, é provável que ela use WHERE em vez de HAVING para filtrar os grupos, o que é um erro de sintaxe, ou que agrupe por uma coluna errada (como id em vez de userid), o que geraria um grupo para cada sessão e nenhum usuário com mais de uma sessão. O método de resolução é o mesmo: verificar se a consulta agrupa por userid, usa avg(duracao) e filtra com HAVING count(*) > 1.
Alternativa E — ❌ Incorreta
Sem o texto literal da alternativa E no enunciado, não é possível apontar o erro específico. Pelo padrão da banca, é provável que ela omita o GROUP BY, o que faria a consulta retornar uma única média geral, ou que use WHERE em vez de HAVING, o que é um erro de sintaxe. O método de resolução é o mesmo: verificar se a consulta agrupa por userid, usa avg(duracao) e filtra com HAVING count(*) > 1.
NÃO CAIA NESSA!
A banca adora trocar HAVING por WHERE para confundir. Lembre-se: WHERE filtra linhas antes do agrupamento e não aceita funções de agregação; HAVING filtra grupos depois do agrupamento e é o único lugar onde count(*) > 1 pode aparecer. Com treino, você enxerga essa troca de longe 💪.
PEGA ESSA DICA!
Na hora da prova, monte a consulta em passos: (1) SELECT userid, avg(duracao) — o que você quer retornar; (2) FROM sessao — de onde vem; (3) GROUP BY userid — como agrupar; (4) HAVING count(*) > 1 — o filtro sobre o grupo. Se a condição envolve uma função de agregação, ela só pode estar no HAVING.