Pular para o conteúdo principal

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

Banco de DadosConsultas e Comandos em SQL
Código
fg165202
Banca
FGV
Órgão
TJ AP
Ano
2024
Cargo
AJ ( )

Quando referenciadas, considere as tabelas relacionais Competidor e Disputa, cujas estruturas e instâncias são descritas abaixo. Todas as colunas são definidas como strings.

 

A tabela Disputa contém as disputas realizadas entre competidores que aparecem na tabela Competidor. Em cada disputa há dois competidores, um com camisa azul e outro com camisa verde.

 

Competidor

 
Nome
A
B
c
D
E
F
 

Disputa

 

Azul

Verde

AB
CA
BA
CE
FA
FD
 

Considerando as tabelas Competidor e Disputa, descritas anteriormente, analise o comando SQL a seguir.

 

delete from Competidor

where (select sum(1)

       from Disputa d where d.azul = Nome)

    < (select sum(1) from Disputa d

       where d.verde = Nome)

 

O número de linhas removidas na execução do comando acima é:

  1. A6;
  2. B4;
  3. C2;
  4. D1;
  5. E0.
Revelar gabarito e comentário

GabaritoD — 1;

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

Comando DELETE com subconsultas correlacionadas

Gabarito: letra D. O comando DELETE remove 1 linha da tabela Competidor. A condição do WHERE compara, para cada competidor, o número de disputas em que ele aparece como azul com o número de disputas em que aparece como verde, e remove apenas aqueles em que o total como azul é menor que o total como verde. Analisando os dados, apenas o competidor E satisfaz essa condição (0 disputas como azul < 1 disputa como verde).

O comando DELETE com subconsultas correlacionadas é uma forma de remover registros com base em condições que dependem de outras tabelas. A subconsulta é avaliada para cada linha da tabela-alvo, usando o valor da coluna Nome da linha atual. No caso, a condição é:

(select sum(1) from Disputa d where d.azul = Nome) < (select sum(1) from Disputa d where d.verde = Nome)

Isso significa: para cada competidor, conte quantas vezes ele aparece na coluna Azul da tabela Disputa e quantas vezes aparece na coluna Verde. Se o número de aparições como azul for estritamente menor que o número de aparições como verde, o competidor é deletado.

Vamos aplicar isso aos dados fornecidos:

Tabela Competidor:

Nome

A

B

c

D

E

F

Tabela Disputa:

Azul

Verde

A

B

C

A

B

A

C

E

F

A

F

D

Agora, para cada competidor, contamos as ocorrências:

  • A: aparece como azul em 1 disputa (linha 1) e como verde em 3 disputas (linhas 2, 3, 5). Como 1 < 3, A seria deletado.

  • B: aparece como azul em 1 disputa (linha 3) e como verde em 1 disputa (linha 1). Como 1 < 1 é falso, B não é deletado.

  • c: aparece como azul em 2 disputas (linhas 2 e 4) e como verde em 0 disputas. Como 2 < 0 é falso, c não é deletado.

  • D: aparece como azul em 0 disputas e como verde em 1 disputa (linha 6). Como 0 < 1, D seria deletado.

  • E: aparece como azul em 0 disputas e como verde em 1 disputa (linha 4). Como 0 < 1, E seria deletado.

  • F: aparece como azul em 2 disputas (linhas 5 e 6) e como verde em 0 disputas. Como 2 < 0 é falso, F não é deletado.

Espera! Isso daria 3 linhas deletadas (A, D, E), mas o gabarito é 1. Onde está o erro?

A pegadinha está na comparação de strings. O comando SQL compara d.azul = Nome e d.verde = Nome. Como todas as colunas são strings, a comparação é sensível a maiúsculas e minúsculas (case-sensitive) em muitos bancos de dados. Na tabela Competidor, o nome 'c' está em minúscula, enquanto na tabela Disputa, os valores são 'C' (maiúsculo). Portanto, 'c' ≠ 'C'.

Vamos refazer a contagem considerando a distinção entre maiúsculas e minúsculas:

  • A: azul = 1 (linha 1), verde = 3 (linhas 2, 3, 5). 1 < 3 → deletado.

  • B: azul = 1 (linha 3), verde = 1 (linha 1). 1 < 1 → falso, não deletado.

  • c (minúsculo): azul = 0 (nenhuma linha tem 'c' minúsculo), verde = 0. 0 < 0 → falso, não deletado.

  • D: azul = 0, verde = 1 (linha 6). 0 < 1 → deletado.

  • E: azul = 0, verde = 1 (linha 4). 0 < 1 → deletado.

  • F: azul = 2 (linhas 5, 6), verde = 0. 2 < 0 → falso, não deletado.

Ainda temos 3 deletados (A, D, E). Mas o gabarito é 1. Há algo mais sutil.

Vamos reler o comando com atenção:

delete from Competidor
where (select sum(1) 
       from Disputa d where d.azul = Nome) 
    < (select sum(1) from Disputa d 
       where d.verde = Nome)

A subconsulta select sum(1) from Disputa d where d.azul = Nome conta o número de linhas em Disputa onde d.azul é igual ao Nome da linha atual de Competidor. Mas note que Nome é uma referência à coluna da tabela externa. Isso é uma subconsulta correlacionada.

Agora, a questão crucial: a comparação d.azul = Nome é case-sensitive? O enunciado diz que todas as colunas são strings, mas não especifica o collation. Em muitos bancos de dados (como PostgreSQL), a comparação de strings é case-sensitive por padrão. Em outros (como MySQL com collation padrão), é case-insensitive. A FGV geralmente considera a comparação case-sensitive quando não especifica.

Se considerarmos case-sensitive, 'c' ≠ 'C', então o competidor 'c' não tem correspondências. Mas ainda temos A, D, E.

Vamos verificar se há alguma outra pegadinha. Talvez a questão seja sobre valores NULL. Se alguma coluna tiver NULL, a comparação = NULL retorna NULL (não verdadeiro), então não conta. Mas não há NULLs nos dados fornecidos.

Outra possibilidade: a questão pode estar considerando que a tabela Disputa tem duplicatas? Não, os dados são únicos.

Vamos recontar com muito cuidado, linha por linha:

Disputa:

  1. A, B

  2. C, A

  3. B, A

  4. C, E

  5. F, A

  6. F, D

Competidor: A, B, c, D, E, F

Para A:

  • azul: linha 1 (A) → 1

  • verde: linhas 2 (A), 3 (A), 5 (A) → 3

  • 1 < 3 → verdadeiro → deleta

Para B:

  • azul: linha 3 (B) → 1

  • verde: linha 1 (B) → 1

  • 1 < 1 → falso → não deleta

Para c (minúsculo):

  • azul: nenhuma linha com 'c' minúsculo → 0

  • verde: nenhuma linha com 'c' minúsculo → 0

  • 0 < 0 → falso → não deleta

Para D:

  • azul: nenhuma linha com 'D' → 0

  • verde: linha 6 (D) → 1

  • 0 < 1 → verdadeiro → deleta

Para E:

  • azul: nenhuma linha com 'E' → 0

  • verde: linha 4 (E) → 1

  • 0 < 1 → verdadeiro → deleta

Para F:

  • azul: linhas 5 (F), 6 (F) → 2

  • verde: nenhuma linha com 'F' → 0

  • 2 < 0 → falso → não deleta

Resultado: A, D, E → 3 linhas deletadas.

Mas o gabarito é 1. Isso indica que a banca considerou algo diferente. Vamos pensar: talvez a banca tenha considerado que a comparação é case-insensitive, então 'c' = 'C'. Nesse caso:

  • c: azul = 2 (linhas 2 e 4, pois 'C' = 'c'), verde = 0. 2 < 0 → falso.

Ainda assim, A, D, E seriam deletados.

Outra possibilidade: a banca pode ter considerado que a subconsulta sum(1) retorna NULL quando não há linhas, e a comparação com NULL resulta em NULL (não verdadeiro). Mas sum(1) sobre zero linhas retorna NULL em SQL padrão. Então, para competidores sem aparições como azul, a primeira subconsulta retorna NULL, e a comparação NULL < (número) é NULL, que é tratado como falso no WHERE. Isso mudaria o resultado!

Vamos aplicar isso:

  • A: azul = 1, verde = 3 → 1 < 3 → verdadeiro → deleta

  • B: azul = 1, verde = 1 → 1 < 1 → falso → não deleta

  • c: azul = NULL (0 linhas), verde = NULL (0 linhas) → NULL < NULL → NULL → falso → não deleta

  • D: azul = NULL, verde = 1 → NULL < 1 → NULL → falso → não deleta

  • E: azul = NULL, verde = 1 → NULL < 1 → NULL → falso → não deleta

  • F: azul = 2, verde = NULL → 2 < NULL → NULL → falso → não deleta

Agora, apenas A é deletado! Isso dá 1 linha, que é o gabarito.

Essa é a pegadinha: SUM(1) sobre um conjunto vazio retorna NULL, e qualquer comparação com NULL resulta em NULL, que é tratado como falso na cláusula WHERE. Portanto, competidores que não aparecem em uma das cores não são deletados, mesmo que o número de aparições na outra cor seja maior.

Vamos confirmar com os dados:

  • A: aparece como azul (1) e verde (3). 1 < 3 → verdadeiro → deletado.

  • B: azul (1), verde (1). 1 < 1 → falso.

  • c: azul (0 → NULL), verde (0 → NULL). NULL < NULL → NULL → falso.

  • D: azul (0 → NULL), verde (1). NULL < 1 → NULL → falso.

  • E: azul (0 → NULL), verde (1). NULL < 1 → NULL → falso.

  • F: azul (2), verde (0 → NULL). 2 < NULL → NULL → falso.

Portanto, apenas A é deletado.

NÃO CAIA NESSA!

A banca explora o comportamento de SUM(1) com conjuntos vazios. Muitos candidatos assumem que SUM(1) retorna 0 quando não há linhas, mas no SQL padrão retorna NULL. Como qualquer comparação com NULL resulta em NULL (não verdadeiro), os competidores que não aparecem em uma das cores não são deletados, mesmo que tenham mais aparições na outra cor. É uma armadilha clássica de lógica de três valores (TRUE, FALSE, UNKNOWN).

1Retorna NULL (não 0)
2Comparação com NULL
Resulta em NULL
WHERE trata como falso
3Efeito no DELETE
Competidor sem aparição em uma cor
Não é removido
SUM(1) em conjunto vazio
LEVELsoulevel.com.br
SUM(1) em conjunto vazio: Retorna NULL (não 0); Comparação com NULL (Resulta em NULL, WHERE trata como falso); Efeito no DELETE (Competidor sem aparição em uma cor, Não é removido)

Alternativa A — ❌ Incorreta

Afirma que 6 linhas seriam removidas. Isso só ocorreria se todos os competidores tivessem mais aparições como verde do que como azul, o que não é o caso. Além disso, ignora o efeito do NULL.

Alternativa B — ❌ Incorreta

Afirma que 4 linhas seriam removidas. Isso ocorreria se considerássemos que SUM(1) retorna 0 para conjuntos vazios e que a comparação é case-sensitive, deletando A, D, E e talvez mais um. Mas o comportamento correto do NULL reduz o número para 1.

Alternativa C — ❌ Incorreta

Afirma que 2 linhas seriam removidas. Isso ocorreria se, por exemplo, apenas A e D fossem deletados, mas o NULL impede D de ser deletado.

Alternativa D — ✅ Correta ⟵ GABARITO

Apenas o competidor A é deletado, pois é o único que tem um número de aparições como azul (1) estritamente menor que como verde (3), e ambas as subconsultas retornam valores não-NULL. Os demais competidores ou têm contagens iguais, ou têm NULL em uma das contagens, o que torna a condição falsa.

Alternativa E — ❌ Incorreta

Afirma que nenhuma linha seria removida. Isso seria verdade se nenhum competidor tivesse mais aparições como verde do que como azul, mas A tem 1 azul e 3 verdes, então a condição é verdadeira para A.

Gabarito: letra D — apenas 1 linha é removida, a do competidor A.

Link permanente: /questoes/fg165202