Pular para o conteúdo principal

Questão de Banco de Dados — Consultas e Comandos em SQL — FUNDATEC 2023

Banco de DadosConsultas e Comandos em SQL
Código
qa537836
Banca
FUNDATEC
Órgão
PROCERGS
Ano
2023
Cargo
ANC ( )

Considere o esquema relacional que representa parte de um sistema de uma biblioteca:

 

Livro(IdLivro,Titulo,Ano,#IdEditora)
Editora(IdEditora, Nome)
Assunto(IdAssunto, Descricao)
LivroAssunto(#IdLivro,#IdAssunto)

 

Legenda: Campos sublinhados compõem a chave primária da tabela e campo precedido de # é uma chave estrangeira


A coordenação de uma biblioteca deseja um relatório para ver os títulos de todos os livros e a quantidade de assuntos que eles abordam, mostrando apenas aqueles que tratam de mais de dois assuntos.


Analise as alternativas de implementação dessa consulta e assinale a alternativa que expressa correta e eficientemente o que o relatório deve mostrar é:

  1. ASELECT TITULO, COUNT(*) FROM LIVRO GROUP BY DESCRICAO WHERE COUNT(*) > 2
  2. BSELECT TITULO, COUNT(DISTINCT IDASSUNTO) FROM LIVRO INNER JOIN ASSUNTO USING(IDLIVRO) GROUP BY TITULO WHERE COUNT(*) > 2
  3. CSELECT TITULO, COUNT(*) FROM LIVRO LEFT OUTER JOIN ASSUNTO USING(IDLIVRO) GROUP BY TITULO HAVING COUNT(*) > 2
  4. DSELECT TITULO, COUNT(IDASSUNTO) FROM LIVRO LEFT OUTER JOIN LIVROASSUNTO LEFT OUTER JOIN ASSUNTO USING (IDLIVRO, IDASSUNTO) GROUP BY TITULO HAVING AVG(IDASSUNTO)>2
  5. ESELECT TITULO, COUNT(DISTINCT IDASSUNTO) FROM LIVRO LEFT OUTER JOIN LIVROASSUNTO USING(IDLIVRO) GROUP BY TITULO HAVING COUNT(DISTINCT IDASSUNTO)>2
Revelar gabarito e comentário

GabaritoE — SELECT TITULO, COUNT(DISTINCT IDASSUNTO) FROM LIVRO LEFT OUTER JOIN LIVROASSUNTO USING(IDLIVRO) GROUP BY TITULO HAVING COUNT(DISTINCT IDASSUNTO)>2

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”.

Consultas SQL com agregação e junção externa

Gabarito: letra E. A consulta correta usa LEFT OUTER JOIN entre LIVRO e LIVROASSUNTO, agrupa por TITULO e filtra com HAVING COUNT(DISTINCT IDASSUNTO) > 2 — essa combinação garante que livros sem assuntos apareçam (com contagem 0) e que apenas os que têm mais de dois assuntos distintos sejam exibidos.

O problema pede um relatório com o título de todos os livros e a quantidade de assuntos que abordam, mostrando apenas os que tratam de mais de dois assuntos. A palavra-chave é "todos os livros": isso exige uma junção externa à esquerda (LEFT OUTER JOIN), porque um livro pode não ter nenhum assunto cadastrado — e uma junção interna (INNER JOIN) o descartaria silenciosamente. A contagem deve ser de assuntos distintos (COUNT(DISTINCT IDASSUNTO)), pois a tabela LIVROASSUNTO é uma tabela de associação muitos-para-muitos e, embora a chave primária composta (IdLivro, IdAssunto) impeça duplicatas exatas, a contagem com COUNT(*) contaria linhas, não assuntos — e a semântica pedida é "quantidade de assuntos".

A cláusula HAVING é o filtro correto para condições sobre o resultado de uma agregação; WHERE não pode ser usado com funções agregadas diretamente, pois filtra linhas antes do agrupamento. O GROUP BY TITULO agrupa os registros por livro, permitindo que a função de agregação conte os assuntos de cada um. A alternativa E combina todos esses elementos: LEFT OUTER JOIN para preservar livros sem assuntos, COUNT(DISTINCT IDASSUNTO) para contar assuntos distintos, GROUP BY TITULO para agrupar por livro e HAVING COUNT(DISTINCT IDASSUNTO) > 2 para filtrar os grupos com mais de dois assuntos.

A pegadinha da banca está em três pontos: (1) usar INNER JOIN em vez de LEFT OUTER JOIN, o que exclui livros sem assuntos; (2) usar COUNT(*) em vez de COUNT(DISTINCT IDASSUNTO), o que conta linhas em vez de assuntos; e (3) usar WHERE em vez de HAVING para filtrar grupos, o que é sintaticamente inválido. A alternativa E é a única que acerta os três.

Critério

Alternativa E (correta)

Alternativas A–D (incorretas)

Junção

LEFT OUTER JOIN entre LIVRO e LIVROASSUNTO (preserva livros sem assuntos)

A: sem junção; B/C: INNER/LEFT JOIN com tabela errada (ASSUNTO não tem IDLIVRO); D: sintaxe de junção inválida

Contagem

COUNT(DISTINCT IDASSUNTO) — conta assuntos distintos

A/C: COUNT(*) conta linhas; D: AVG(IDASSUNTO) calcula média, não contagem

Filtro pós-agregação

HAVING COUNT(DISTINCT IDASSUNTO) > 2 — correto

A/B: WHERE COUNT(*) > 2 — inválido (agregado no WHERE)

Agrupamento

GROUP BY TITULO — agrupa por livro

A: GROUP BY DESCRICAO — coluna de outra tabela, sem junção

Resultado

Títulos com mais de 2 assuntos distintos, incluindo livros sem assuntos (contagem 0)

Exclui livros sem assuntos, conta errado ou erro de sintaxe

Alternativa A — ❌ Incorreta

Esta alternativa usa GROUP BY DESCRICAO, mas a coluna DESCRICAO pertence à tabela ASSUNTO, não à tabela LIVRO. Além disso, usa WHERE COUNT(*) > 2, o que é inválido — WHERE não pode conter funções agregadas; o correto seria HAVING. A consulta também não faz nenhuma junção, então não relaciona livros a assuntos.

Alternativa B — ❌ Incorreta

Esta alternativa usa INNER JOIN entre LIVRO e ASSUNTO com USING(IDLIVRO), mas a tabela ASSUNTO não possui a coluna IDLIVRO — a associação entre livros e assuntos é feita pela tabela LIVROASSUNTO. Além disso, usa WHERE COUNT(*) > 2, que é inválido; o correto seria HAVING. A junção interna também descartaria livros sem assuntos.

Alternativa C — ❌ Incorreta

Esta alternativa usa LEFT OUTER JOIN entre LIVRO e ASSUNTO com USING(IDLIVRO), mas a tabela ASSUNTO não possui a coluna IDLIVRO — a associação correta é via LIVROASSUNTO. Além disso, usa COUNT(*), que conta linhas em vez de assuntos distintos. O HAVING COUNT(*) > 2 está correto sintaticamente, mas a junção errada invalida a consulta.

Alternativa D — ❌ Incorreta

Esta alternativa tem múltiplos erros: (1) a sintaxe LEFT OUTER JOIN LIVROASSUNTO LEFT OUTER JOIN ASSUNTO USING (IDLIVRO, IDASSUNTO) é inválida — não se pode encadear junções dessa forma sem especificar as condições de junção para cada uma; (2) usa AVG(IDASSUNTO) > 2 em vez de COUNT(DISTINCT IDASSUNTO) > 2, o que calcula a média dos IDs em vez de contar assuntos distintos; (3) a condição HAVING AVG(IDASSUNTO) > 2 não atende ao requisito de "mais de dois assuntos".

Alternativa E — ✅ Correta ⟵ GABARITO

Esta alternativa usa LEFT OUTER JOIN entre LIVRO e LIVROASSUNTO com USING(IDLIVRO), o que preserva todos os livros, inclusive os sem assuntos. Agrupa por TITULO e usa COUNT(DISTINCT IDASSUNTO) para contar assuntos distintos por livro. O HAVING COUNT(DISTINCT IDASSUNTO) > 2 filtra corretamente os grupos com mais de dois assuntos. Essa é a única alternativa que atende a todos os requisitos do relatório.

PEGA ESSA DICA!

Para questões de SQL com agregação, lembre-se da sequência lógica: FROMJOINWHEREGROUP BYHAVINGSELECT. O WHERE filtra linhas antes do agrupamento; o HAVING filtra grupos depois. Use LEFT OUTER JOIN quando precisar preservar registros sem correspondência na tabela à direita. E para contar itens distintos, use COUNT(DISTINCT coluna).

Gabarito: letra E

Link permanente: /questoes/qa537836