Pular para o conteúdo principal

Questão de Banco de Dados — SQL — FGV 2024

Banco de DadosSQL
Código
fg077359
Banca
FGV
Órgão
CVM
Ano
2024
Nível
Superior
Cargo
Analista - Perfil 8 - TI / Sistemas e Desenvolvimento - Tarde
William está trabalhando com a base de dados de uma clínica, onde estão presentes as entidades descritas a seguir.Paciente (Id: Integer PK,Nome: Varchar(50))Medico (Id: Integer PK, Nome: Varchar(50))Atendimento (Id: Integer PK,IdPaciente: Integer FK(Paciente),IdMedico: Integer FK(Medico),Data: Date)Para que William obtenha os nomes dos pacientes que foram tratados por todos os médicos, a instrução SQL a ser utilizada é:
  1. Aselect p.nome from paciente p, atendimento awhere a.idpaciente = p.idand a.idmedico = all (select id from medico);
  2. Bselect p.nome from paciente p where not exists (select id from medico m where id not in (select idmedico from atendimento where idpaciente = p.id));
  3. Cselect p.nome from paciente p where exists (select idmedico from atendimento where idpaciente = p.id);
  4. Dselect p.nome from paciente p, atendimento awhere a.idpaciente=p.id group by p.nomehaving count(*) = (select count(*) from medico);
  5. Eselect p.nome from paciente p, atendimento awhere a.idpaciente = p.id anda.idmedico = any (select id from medico);
Revelar gabarito e comentário

GabaritoB — select p.nome from paciente p where not exists ( select id from medico m where id not in ( select idmedico from atendimento where idpaciente = p.id));

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

Divisão relacional em SQL (pacientes tratados por todos os médicos)

Gabarito: letra B. A consulta correta utiliza a dupla negação (NOT EXISTS) para implementar a divisão relacional: seleciona pacientes para os quais não existe médico que não tenha realizado atendimento. Esse padrão equivale à lógica “para todo X, existe Y” e é o único que garante a obtenção dos pacientes que foram tratados por todos os médicos.

A questão testa o conhecimento de como expressar uma operação de divisão em SQL, um tema clássico de bancos de dados relacionais. A tabela Atendimento relaciona pacientes e médicos; o objetivo é encontrar pacientes que possuem ao menos um registro com cada médico.

Alternativa

Descrição

Correta?

Motivo

A

a.idmedico = ALL (SELECT id FROM medico)

Compara um único valor com todos os IDs; impossível ser verdade (exceto se houver um só médico).

B

Dupla negação (NOT EXISTS com NOT IN)

Implementa a divisão relacional: seleciona pacientes para os quais não existe médico que não tenha atendido.

C

EXISTS (SELECT idmedico FROM atendimento WHERE idpaciente = p.id)

Retorna pacientes com pelo menos um atendimento, não todos os médicos.

D

GROUP BY ... HAVING COUNT(*) = (SELECT COUNT(*) FROM medico)

Conta total de registros, não médicos distintos; paciente com múltiplas consultas ao mesmo médico falseia o resultado.

E

a.idmedico = ANY (SELECT id FROM medico)

Equivale a IN; retorna pacientes que foram atendidos por pelo menos um médico, não todos.

Alternativa A — ❌ Incorreta

Usa a.idmedico = ALL (SELECT id FROM medico). Essa condição compara um único valor (o idmedico de uma linha da junção) com o conjunto de todos os id de médicos. Para ser verdadeira, aquela linha específica deveria ter um idmedico que fosse igual a todos os ids simultaneamente – o que é impossível (a menos que haja um só médico). Não realiza a divisão.

Alternativa B — ✅ Correta ⟵ GABARITO

SELECT p.nome FROM paciente p WHERE NOT EXISTS (SELECT id FROM medico m WHERE id NOT IN (SELECT idmedico FROM atendimento WHERE idpaciente = p.id)). Essa é a forma clássica: para cada paciente, verifica se não existe um médico que não tenha atendido aquele paciente. Se a subconsulta retornar vazia, significa que o paciente foi atendido por todos. Correta.

Alternativa C — ❌ Incorreta

SELECT p.nome FROM paciente p WHERE EXISTS (SELECT idmedico FROM atendimento WHERE idpaciente = p.id). Retorna pacientes que possuem pelo menos um atendimento (qualquer médico), não todos. Não atende ao requisito.

Alternativa D — ❌ Incorreta

SELECT p.nome FROM paciente p, atendimento a WHERE a.idpaciente=p.id GROUP BY p.nome HAVING COUNT(*) = (SELECT COUNT(*) FROM medico). Conta o número total de registros de atendimento por paciente, não o número de médicos distintos. Um paciente que visitou o mesmo médico várias vezes teria COUNT(*) maior que o número de médicos, falseando o resultado. Além disso, a junção implícita sem DISTINCT não impede duplicatas.

Alternativa E — ❌ Incorreta

SELECT p.nome FROM paciente p, atendimento a WHERE a.idpaciente = p.id AND a.idmedico = ANY (SELECT id FROM medico). Equivale a IN: retorna pacientes que tiveram atendimento com algum médico (pelo menos um), não todos.

NÃO CAIA NESSA!

A banca explora a confusão entre ALL/ANY e a contagem simples de atendimentos. Candidatos desavisados escolhem a alternativa D (que parece intuitiva) ou A (que usa a palavra ALL). O padrão correto é o da dupla negação (NOT EXISTS com NOT IN), típico de consultas de divisão.

PEGA ESSA DICA!

Para memorizar: “divisão relacional = para todo X, não existe X sem Y”. Decore a estrutura com NOT EXISTS (SELECT ... WHERE NOT IN (SELECT ...)). Sempre desconfie de consultas que usam ALL ou ANY diretamente, pois elas comparam linha a linha, não conjuntos.

Gabarito: letra B.

Link permanente: /questoes/fg077359