Pular para o conteúdo principal

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

Banco de DadosConsultas e Comandos em SQL
Código
fg161117
Banca
FGV
Órgão
CAM DEP
Ano
2023
Cargo
AL ( )

Quando mencionada, considere a tabela relacional intitulada fibo, com duas colunas, cuja instância, não necessariamente nessa ordem, é exibida a seguir.

 

Tabela fibo

PN
10
21
31
42
53
65
78
813
921
1034
 

A coluna da esquerda enumera as linhas, continuamente, e a coluna da direita armazena os dez primeiros elementos da sequência de Fibonacci, na qual os dois primeiros termos são 0 e 1, por definição, e cada termo subsequente é a soma dos dois termos anteriores.

 

----------------------------------------------------------------

 

Suponha que a tabela fibo, apresentada anteriormente, tenha sido danificada, e sua instância corrente seja a que segue.

 
PN
10
21
31
65
78
 

Para restaurar a tabela, foi produzido o comando SQL a seguir.

 

insert into fibo

select f2.P + 1, f1.N + f2.N

from fibo f1, fibo f2

where f1.P = f2.P - 1

and f2.P < 10

and not exists

(select * from fibo f3

where f1.N + f2.N = f3.N and f3.P > f2.P)

 

À luz das características de funcionamento do SQL, o número mínimo de vezes que esse comando deve ser acionado para restaurar a instância original, é

  1. A1.
  2. B2.
  3. C3.
  4. D4.
  5. E5.
Revelar gabarito e comentário

GabaritoC — 3.

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

Resolução

Gabarito: letra C — a conta chega a 3 execuções — alternativa C.

A ideia por trás

Em SQL, um comando INSERT ... SELECT insere na tabela todas as linhas que o SELECT retorna, mas apenas as que ainda não existem (se houver restrição de unicidade) ou as que passam no filtro. Aqui, o comando é um self-join: ele combina a tabela com ela mesma, pareando cada linha com a seguinte (f1.P = f2.P-1), e tenta inserir uma nova linha com o próximo número da sequência (soma dos dois anteriores). A cláusula NOT EXISTS impede que um valor já presente em uma posição posterior seja inserido novamente.

A sequência de Fibonacci é recursiva: cada termo é a soma dos dois anteriores. Para gerar um termo, os dois anteriores precisam já estar na tabela. O comando só consegue gerar termos cujos dois antecessores estão presentes. Como a tabela danificada tem lacunas (faltam P=4,5,8,9,10), cada execução só consegue preencher os termos imediatamente seguintes aos pares existentes. A cada execução, novos termos são adicionados, o que permite gerar mais termos na próxima execução.

Esta questão testa o entendimento de como um INSERT ... SELECT com self-join e subconsulta correlacionada se comporta em múltiplas execuções: cada execução só insere os termos que podem ser calculados a partir dos dados já presentes, então é preciso simular execução por execução até completar a tabela.

O que a questão dá

  • tabela fibo original com 10 linhas (P de 1 a 10, N = Fibonacci)

  • tabela danificada com 5 linhas: (1,0), (2,1), (3,1), (6,5), (7,8)

  • comando SQL: INSERT INTO fibo SELECT f2.P+1, f1.N+f2.N FROM fibo f1, fibo f2 WHERE f1.P = f2.P-1 AND f2.P < 10 AND NOT EXISTS (SELECT * FROM fibo f3 WHERE f1.N+f2.N = f3.N AND f3.P > f2.P)

O que queremos: o número mínimo de execuções do comando para restaurar a tabela original

Passo 1 — Listar os pares possíveis na primeira execução

O comando funciona pareando cada linha com a seguinte (f1.P = f2.P-1). Na tabela danificada, os pares são (1,2), (2,3) e (6,7). Precisamos ver o que cada par tenta inserir.

Por que esta fórmula: A condição f1.P = f2.P-1 define o par; o INSERT tenta inserir P = f2.P+1 e N = f1.N+f2.N.

pares:(1,2),(2,3),(6,7)\boxed{\text{pares}: (1,2), (2,3), (6,7)}
NÃO CAIA NESSA!

Esquecer que o par (6,7) também é válido, pois a condição não exige que os P sejam consecutivos a partir de 1.

Passo 2 — Calcular as inserções da primeira execução

Para cada par, calculamos o que seria inserido e verificamos se já existe na tabela (via NOT EXISTS).

Por que esta fórmula: Para o par (f1, f2), a nova linha é (f2.P+1, f1.N+f2.N). O NOT EXISTS impede inserir se o valor N já existir em uma linha com P > f2.P.

insere (4,2) e (8,13); (3,1) já existe

NÃO CAIA NESSA!

Achar que (3,1) seria inserido de novo, mas o NOT EXISTS bloqueia porque N=1 já existe com P=3 > 2.

Passo 3 — Atualizar a tabela após a primeira execução

A tabela agora tem novas linhas, que permitem novos pares na próxima execução.

tabela: (1,0), (2,1), (3,1), (4,2), (6,5), (7,8), (8,13)

NÃO CAIA NESSA!

Não atualizar mentalmente a tabela e continuar com a antiga.

Passo 4 — Repetir para a segunda execução

Com os novos dados, os pares possíveis agora incluem (3,4) e (7,8). Calculamos as inserções.

Por que esta fórmula: Mesma lógica: para cada par, tenta inserir (f2.P+1, f1.N+f2.N) se não existir.

insere(5,3)e(9,21)\boxed{\text{insere} (5,3) \text{e} (9,21)}
NÃO CAIA NESSA!

Esquecer que (7,8) agora é um par válido, pois 8 foi inserido na execução anterior.

Passo 5 — Atualizar a tabela após a segunda execução

A tabela agora tem (5,3) e (9,21), permitindo novos pares.

tabela: (1,0), (2,1), (3,1), (4,2), (5,3), (6,5), (7,8), (8,13), (9,21)

NÃO CAIA NESSA!

Não perceber que agora faltam apenas P=10.

Passo 6 — Repetir para a terceira execução

Agora os pares possíveis incluem (4,5) e (8,9). Calculamos as inserções.

Por que esta fórmula: Mesma lógica.

insere (10,34); (6,5) já existe

NÃO CAIA NESSA!

Achar que (6,5) seria inserido, mas já existe com P=6 > 5.

Passo 7 — Conferir se a tabela está completa

Após a terceira execução, todos os termos de 1 a 10 estão presentes.

tabela completa: (1,0), (2,1), (3,1), (4,2), (5,3), (6,5), (7,8), (8,13), (9,21), (10,34)

NÃO CAIA NESSA!

Contar as linhas faltantes (5) e achar que precisa de 5 execuções, mas cada execução pode inserir mais de uma linha.

Resposta: 3 execuções — alternativa C

Link permanente: /questoes/fg161117