Questão de Banco de Dados — Consultas e Comandos em SQL — FCC 2026
Banco de Dados›Consultas e Comandos em SQL
Código
fc142174
Banca
FCC
Órgão
SCGE PE
Ano
2026
Cargo
Ges Gov ( )
No banco de dados PostgreSQL da SCGE, instalado e funcionando em condições ideais, a tabela controle possui os campos id (SERIAL), descricao (VARCHAR(100)), valor (NUMERIC(10,2)) e data (DATE). Foi identificado que alguns lançamentos da tabela controle podiam estar duplicados. Com o objetivo de realizar uma auditoria e a correção, o comando SQL que elimina corretamente as duplicidades, mantendo apenas um registro de cada grupo, é:
ADELETE FROM controle WHERE id IN(SELECT MAX(id) FROM controle GROUP BY id, descricao, valor, data HAVING COUNT(*) > 1);
BDELETE FROM controle WHERE id IN (SELECT MIN(id) FROM controle GROUP BY descricao, data);
CUPDATE controle SET valor=0 WHERE id IN (SELECT MIN(id) FROM controle GROUP BY descrecao, valor,data);
DDELETE FROM controle c1 USING controle c2 WHERE c1.id < c2.id AND c1 AND.descricao=c2.descricao AND c1.valor=c2.valor AND c1.data= c2.data;
EUPDATE controle SET descricao = descricao || '-duplicado' WHERE id IN (SELECT id FROM (SELECT id, ROW_NUMBER() OVER (PARTITION BY descricao, valor, data ORDER BY id) AS rn FROM controle) t WHERE rn > 1);
Revelar gabarito e comentário▾
GabaritoD — DELETE FROM controle c1 USING controle c2
WHERE c1.id < c2.id AND c1
AND.descricao=c2.descricao AND c1.valor=c2.valor AND c1.data= c2.data;
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”.
Eliminação de duplicatas no PostgreSQL: a sintaxe DELETE ... USING
Gabarito: letra D. O comando DELETE FROM controle c1 USING controle c2 WHERE c1.id < c2.id AND c1.descricao = c2.descricao AND c1.valor = c2.valor AND c1.data = c2.data é o único que elimina corretamente as duplicidades, mantendo apenas um registro de cada grupo, pois usa a cláusula USING do PostgreSQL para fazer um self-join (auto-relacionamento) e apagar apenas as linhas de menor id que possuem correspondência em outra linha com os mesmos valores de descricao, valor e data. As demais alternativas ou possuem erros de sintaxe, ou não agrupam corretamente, ou não são comandos de exclusão.
O problema de eliminar duplicatas é clássico em bancos de dados. A ideia central é identificar, para cada grupo de registros que compartilham os mesmos valores nas colunas que definem a duplicidade (aqui, descricao, valor e data), qual registro deve ser mantido (geralmente o de menor id, por ser o mais antigo) e quais devem ser removidos (todos os demais). A dificuldade está em escrever um comando DELETE que faça essa seleção de forma correta e eficiente, respeitando a sintaxe do SGBD utilizado.
No PostgreSQL, uma das formas mais elegantes e diretas de fazer isso é usando a cláusula USING no comando DELETE. Essa cláusula permite que você especifique tabelas adicionais que serão usadas na condição WHERE do DELETE, permitindo um self-join sem precisar de uma subconsulta. A sintaxe geral é:
DELETE FROM tabela_alvo alias_alvo
USING tabela_auxiliar alias_auxiliar
WHERE condicao_de_join_e_filtro;
No caso da questão, a tabela controle é usada tanto como alvo (c1) quanto como auxiliar (c2). A condição c1.id < c2.id garante que, para cada par de registros duplicados, apenas o registro com o id menor (o mais antigo) seja considerado para exclusão, pois ele será o c1 em relação a um c2 com id maior. As condições adicionais c1.descricao = c2.descricao, c1.valor = c2.valor e c1.data = c2.data garantem que os registros comparados são de fato duplicados, ou seja, possuem os mesmos valores nas colunas que definem a duplicidade. Assim, para cada grupo de duplicatas, apenas o registro de menor id sobrevive, e todos os outros são excluídos.
Vamos analisar por que as outras alternativas falham:
Alternativa A: A subconsulta agrupa por id, descricao, valor, data. Como id é uma chave primária (SERIAL), cada grupo terá exatamente um registro, e a condição HAVING COUNT(*) > 1 nunca será verdadeira. Portanto, nenhuma linha será excluída.
Alternativa B: A subconsulta agrupa apenas por descricao, data, ignorando o campo valor. Isso faria com que registros com a mesma descrição e data, mas com valores diferentes, fossem considerados duplicados, excluindo indevidamente um deles. Além disso, a subconsulta retorna o MIN(id) de cada grupo, e o DELETE removeria esses registros, ou seja, manteria os de maior id, o que é o oposto do desejado (geralmente queremos manter o mais antigo).
Alternativa C: É um comando UPDATE, não um DELETE. Além disso, a subconsulta agrupa por descricao, valor, data (note o erro de digitação descrecao), mas a intenção de zerar o valor de um registro por grupo não faz sentido para eliminar duplicidades.
Alternativa E: É um comando UPDATE que marca os registros duplicados (aqueles com rn > 1 na janela ROW_NUMBER()) adicionando o sufixo '-duplicado' à descrição. Isso não elimina as duplicidades, apenas as renomeia, o que não atende ao objetivo de correção.
A pegadinha desta questão está em reconhecer a sintaxe correta do DELETE ... USING no PostgreSQL e em entender que a alternativa A, embora pareça lógica, é ineficaz porque agrupa por id, que é único. A alternativa B, por sua vez, é perigosa porque agrupa por colunas insuficientes, podendo excluir registros que não são duplicados.
Critério
Alternativa D (gabarito)
Alternativa A
Alternativa B
Alternativa E
Tipo de comando
DELETE com USING (self-join)
DELETE com subconsulta
DELETE com subconsulta
UPDATE (não exclui)
Critério de duplicidade
descricao, valor, data (correto)
id, descricao, valor, data (incorreto – inclui PK)
descricao, data (incompleto – omite valor)
descricao, valor, data (correto, mas não exclui)
Registro mantido
Menor id (mais antigo)
Nenhum (nunca encontra duplicatas)
Maior id (mais recente) – inverso do desejado
Todos (apenas renomeia com sufixo)
Efeito prático
Remove duplicatas corretamente
Nenhuma linha removida
Remove registros legítimos
Não elimina duplicidades
Sintaxe PostgreSQL
Válida (DELETE ... USING)
Válida, mas lógica ineficaz
Válida, mas lógica incorreta
Válida, mas objetivo errado
Alternativa A — ❌ Incorreta
A subconsulta agrupa por id, descricao, valor, data. Como id é uma chave primária (SERIAL), cada grupo terá exatamente um registro, e a condição HAVING COUNT(*) > 1 nunca será verdadeira. Portanto, o comando não excluirá nenhuma linha, falhando em eliminar as duplicidades.
Alternativa B — ❌ Incorreta
A subconsulta agrupa apenas por descricao, data, ignorando o campo valor. Isso faria com que registros com a mesma descrição e data, mas com valores diferentes, fossem considerados duplicados, excluindo indevidamente um deles. Além disso, a subconsulta retorna o MIN(id) de cada grupo, e o DELETE removeria esses registros, ou seja, manteria os de maior id, o que é o oposto do desejado (geralmente queremos manter o mais antigo).
Alternativa C — ❌ Incorreta
É um comando UPDATE, não um DELETE. Além disso, a subconsulta agrupa por descricao, valor, data (note o erro de digitação descrecao), mas a intenção de zerar o valor de um registro por grupo não faz sentido para eliminar duplicidades.
Alternativa D — ✅ Correta ⟵ GABARITO
Usa a cláusula USING do PostgreSQL para fazer um self-join na tabela controle. A condição c1.id < c2.id garante que, para cada par de registros duplicados, apenas o registro com o id menor (o mais antigo) seja considerado para exclusão. As condições adicionais c1.descricao = c2.descricao, c1.valor = c2.valor e c1.data = c2.data garantem que os registros comparados são de fato duplicados. Assim, para cada grupo de duplicatas, apenas o registro de menor id sobrevive, e todos os outros são excluídos.
Alternativa E — ❌ Incorreta
É um comando UPDATE que marca os registros duplicados (aqueles com rn > 1 na janela ROW_NUMBER()) adicionando o sufixo '-duplicado' à descrição. Isso não elimina as duplicidades, apenas as renomeia, o que não atende ao objetivo de correção.
NÃO CAIA NESSA!
A banca explora a confusão entre agrupar por colunas que definem a duplicidade e agrupar por colunas que incluem a chave primária. Na alternativa A, o GROUP BY id torna cada grupo único, anulando o efeito do HAVING COUNT(*) > 1. Já na alternativa B, a omissão do campo valor no GROUP BY faz com que registros com valores diferentes sejam tratados como duplicados. Fique atento: a chave primária nunca deve entrar no GROUP BY quando o objetivo é encontrar duplicatas.
PEGA ESSA DICA!
Para eliminar duplicatas no PostgreSQL, você pode usar a sintaxe DELETE ... USING com um self-join, como na alternativa D, ou usar uma subconsulta com ROW_NUMBER() e depois excluir os registros com rn > 1. A primeira é mais direta e eficiente para tabelas grandes. Lembre-se de sempre incluir todas as colunas que definem a duplicidade no critério de comparação.