Questão de Banco de Dados — Consultas e Comandos em SQL — FGV 2025
Banco de Dados›Consultas e Comandos em SQL
Código
fg169074
Banca
FGV
Órgão
DPE RO
Ano
2025
Cargo
TDP ( )
Seja o seguinte esquema relacional de banco de dados: tb_processos(id_processo, numero_processo, tipo, status, data_abertura)
Restrições:
• id_processo é chave primária
• numero_processo não pode ser nulo
• tipo pode assumir os valores {"Ação de Alimentos", "Defesa Criminal"}.
• status pode assumir os valores {"Em andamento", "Arquivado", "Sentenciado"}
tb_movimentacoes(id_movimentacao, descricao,
data_movimentacao, id_processo<FK>)
Restrições:
• id_movimentacao é chave primária
• descricao não pode ser nulo
• descricao pode assumir os valores { "Petição inicial protocolada", "Audiência realizada"}.
• id_processo é chave estrangeira e referencia a tabela tb_processos
Submeteu-se ao sistema que gerencia esse banco de dados relacional a consulta:
select mov.descricao, mov.data_movimentacao
from tb_movimentacoes mov
where exists
( select proc.id_processo from tb_processos proc
where proc.id_processo=mov.id_processo
and proc.status='Arquivado' )
O otimizador de consultas do sistema, ao avaliar a consulta, identificou tratar-se de um caso de consulta correlata, com uma subconsulta aninhada referenciando um elemento de dado da consulta externa.
Considerando que o otimizador decidiu e é capaz de implementar a melhor opção de otimização, qual das opções apresenta uma consulta equivalente à anteriormente proposta, após a aplicação da técnica de desalinhamento?
Aselect mov.descricao, mov.data_movimentacao from tb_movimentacoes mov where mov.id_processo in (select proc.id_processo from tb_processos proc where proc.status='Arquivado')
Bselect mov.descricao, mov.data_movimentacao from tb_movimentacoes mov left join tb_processos proc on proc.id_processo=mov.id_processo where proc.status='Arquivado'
Cselect mov.descricao, mov.data_movimentacao from tb_movimentacoes mov natural join tb_processos proc where proc.status='Arquivado'
Dselect mov.descricao, mov.data_movimentacao from tb_movimentacoes mov where mov.id_processo any (select proc.id_processo from tb_processos proc where proc.status='Arquivado')
Eselect mov.descricao, mov.data_movimentacao from tb_movimentacoes mov union select proc.id_processo from tb_processos proc where proc.status='Arquivado'
Revelar gabarito e comentário▾
GabaritoC — select mov.descricao, mov.data_movimentacao
from tb_movimentacoes mov natural join tb_processos proc
where proc.status='Arquivado'
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”.
Desalinhamento de Subconsultas Correlatas em SQL
Gabarito: letra C. A técnica de desalinhamento (ou unnesting) transforma a subconsulta correlata em uma junção equivalente, e a opção que implementa corretamente essa transformação é a que usa natural join entre tb_movimentacoes e tb_processos, filtrando proc.status='Arquivado'. A consulta original retorna as movimentações cujo processo associado está arquivado — exatamente o que a junção natural entre as duas tabelas, seguida do filtro de status, produz.
A consulta original é um exemplo clássico de subconsulta correlata: a subconsulta interna referencia a consulta externa através da condição proc.id_processo = mov.id_processo. Para cada linha de tb_movimentacoes, o SGBD executa a subconsulta, verificando se existe um processo com aquele id_processo e com status = 'Arquivado'. O operador EXISTS retorna verdadeiro se a subconsulta retornar pelo menos uma linha, e falso caso contrário.
O desalinhamento (ou unnesting) é uma otimização que elimina a correlação, transformando a subconsulta em uma operação de junção. A ideia é que, em vez de executar a subconsulta para cada linha da tabela externa, o otimizador pode combinar as duas tabelas de uma vez e depois aplicar o filtro. A junção natural (NATURAL JOIN) é a forma mais direta: ela combina as linhas das duas tabelas onde os valores das colunas com o mesmo nome são iguais — aqui, id_processo — e o resultado é filtrado por status = 'Arquivado'. Isso produz exatamente o mesmo conjunto de movimentações que a consulta original.
Vamos ver por que as outras opções falham:
A) Usa IN com uma subconsulta não correlata. Embora semanticamente equivalente em muitos casos, a subconsulta não é correlata e a transformação não é um desalinhamento típico — além disso, a opção não usa junção, que é a técnica de desalinhamento mencionada.
B) Usa LEFT JOIN, que preserva todas as linhas de tb_movimentacoes, mesmo aquelas sem processo correspondente. O filtro proc.status='Arquivado' no WHERE elimina as linhas sem correspondência (porque proc.status seria NULL), mas a semântica de LEFT JOIN não é a mais adequada para representar a equivalência com EXISTS — um INNER JOIN seria mais natural.
D) A sintaxe mov.id_processo any (...) está incorreta — o correto seria = ANY (...), e mesmo assim não é a forma de desalinhamento por junção.
E) Usa UNION, que combina resultados de duas consultas, mas não representa a interseção lógica exigida — além de tentar unir colunas diferentes (descricao, data_movimentacao com id_processo), o que é semanticamente inválido.
A pegadinha aqui é que a banca testa se o candidato conhece a técnica de desalinhamento e consegue identificar a junção equivalente. Muitos candidatos podem marcar a opção A, que usa IN, mas a questão pede especificamente a técnica de desalinhamento, que é a transformação em junção.
Desalinhamento (unnesting): Subconsulta correlata (Referencia consulta externa, EXISTS por linha); Transformação (Junção equivalente, Filtro após juntar); Formas corretas (NATURAL JOIN, INNER JOIN); Formas incorretas (LEFT JOIN (preserva sem correspondência), UNION (união, não interseção), IN (não é junção))
Alternativa A — ❌ Incorreta
A opção A usa IN com uma subconsulta não correlata. Embora semanticamente equivalente à consulta original (retorna as movimentações cujo id_processo está na lista de processos arquivados), ela não representa a técnica de desalinhamento por junção. O desalinhamento transforma a subconsulta correlata em uma operação de junção, não em outra subconsulta. Além disso, a subconsulta aqui não é correlata, pois não referencia a consulta externa.
Alternativa B — ❌ Incorreta
A opção B usa LEFT JOIN, que preserva todas as linhas de tb_movimentacoes, mesmo aquelas sem processo correspondente. O filtro proc.status='Arquivado' no WHERE elimina as linhas sem correspondência (porque proc.status seria NULL), mas a semântica de LEFT JOIN não é a mais adequada para representar a equivalência com EXISTS — um INNER JOIN seria mais natural. A junção natural (opção C) é a forma correta de desalinhamento.
Alternativa C — ✅ Correta ⟵ GABARITO
A opção C usa NATURAL JOIN, que combina as linhas das duas tabelas onde os valores das colunas com o mesmo nome são iguais — aqui, id_processo. O filtro proc.status='Arquivado' seleciona apenas as movimentações cujo processo está arquivado. Isso é exatamente o que a consulta original com EXISTS faz: retorna as movimentações para as quais existe um processo arquivado com o mesmo id_processo. A junção natural é a forma clássica de desalinhamento de subconsultas correlatas.
Alternativa D — ❌ Incorreta
A opção D usa a sintaxe mov.id_processo any (...), que está incorreta. O operador correto seria = ANY (...), e mesmo assim não é a forma de desalinhamento por junção. A sintaxe ANY é usada para comparar um valor com qualquer elemento de uma lista, mas não é a técnica de desalinhamento mencionada na questão.
Alternativa E — ❌ Incorreta
A opção E usa UNION, que combina os resultados de duas consultas. No entanto, a consulta original é uma interseção lógica (movimentações cujo processo está arquivado), não uma união. Além disso, a segunda consulta seleciona proc.id_processo, que não é compatível com as colunas descricao e data_movimentacao da primeira — a operação UNION exige que as colunas correspondam em número e tipo. Portanto, a opção E é semanticamente inválida.
PEGA ESSA DICA!
Para identificar a técnica de desalinhamento, procure pela transformação da subconsulta correlata em uma junção. A junção natural (NATURAL JOIN) ou INNER JOIN com condição explícita são as formas mais comuns. Lembre-se: EXISTS com correlação equivale a uma junção interna com filtro, não a LEFT JOIN ou UNION.