Ir ao conteúdo
  • Cadastre-se

Deletar linhas dupliacas no SQL


gustavo1982

Posts recomendados

Boa tarde, gente. COmo fui ajudado anteriormente por você, venho mais uma vez, pedir orientação.

Eu tenho uma tabela que eu acabei duplicando algumas linhas por acidente por executar sintaxes deixadas soltas na tela do interpretador do banco. Eu estava realisando buscas no meu banco, de acordo com alguns parametros e a resposta da busca eu acabei clonando dentro da tabela sem querer, porque eu usei a resposta do select dentro de um insert que eu fiz pra criar uma tabela nova com a resposta desta busca.

O respectivo comando da minha busca foi:

select * from dbo.Ocorrencias where (tipo_cod = 307 or tipo_cod = 107 or tipo_cod = 91 or tipo_cod = 114 or tipo_cod = 113 or tipo_cod = 142 or tipo_cod = 412) and (regiao = 23) and (datacriacao between '2012/01/01 00:00:00'and '2012/08/31 23:59:59') order by datacriacao

A resposta dava exatas 703 linhas. Só que depois da confusão que eu fiz, o mesmo select agora da 1406, ou seja, ele me devolve o que eu quero, só que agora está tudo aparecendo duas vezes. Eu tentei fazer um "delete from" pra poder apagar as linhas clonadas mas estou falhando em redigir uma sintaxe que funcione só pras linhas clonadas dentro do período de busca que eu usei no select.

Agradeço pelo espaço para duvidas aqui do forum cdh.

Link para o comentário
Compartilhar em outros sites

Olá.

Sua tabela de Ocorrencias possui algum campo único, que não se repita em nenhum registro? Alguma Primary Key?

Se NÃO tiver, ACHO que não tem jeito de fazer um único comando

se POSSUIR, aí ACHO que tem como fazer.

Se POSSUIR, passe a estrutura da sua tabela, ou só os campos mais importantes, que tento montar uma query.

Link para o comentário
Compartilhar em outros sites

Olá.

Sua tabela de Ocorrencias possui algum campo único, que não se repita em nenhum registro? Alguma Primary Key?

Se NÃO tiver, ACHO que não tem jeito de fazer um único comando

se POSSUIR, aí ACHO que tem como fazer.

Se POSSUIR, passe a estrutura da sua tabela, ou só os campos mais importantes, que tento montar uma query.

Sim, possui um código de identificação das ocorrências gravadas na tabela. Tem o campo ID, que automatico a cada linha ele é gerado, tem o campo num que é (varchar(20), que contém o código que identifica cada registro. Esse campo num que é o mais importante. Eu preciso apagar as linhas em que esses registros(campo num) foram duplicados.

Estrutura

ID int PK

num varchar(20)

AISP int

RISP int

DP int

tipo_cod int

diasemana varchar(15)

datacriacao smalldatetime

datafechamento smalldatetime

SitucacaoFinal varchar(100)

tipo_logradouro varchar(50)

nome_logradouro varchar(200)

num_logradouro int

complemento varchar(200)

referencia varchar(200)

bairro varchar(100)

tipo_local varchar(100)

municipio varchar(150)

falecido varchar(100)

preso varchar(100)

regiao varchar(100)

tipo_envolvido varchar(100)

data_nascimento varchar(20)

idade int

cor varchar(100)

sexo varchar(100)

maioridade varchar(100)

profissao varchar(100)

escolaridade varchar(100)

estadocivil varchar(100)

naturalidade varchar(100)

Geometry varbinary(MAX)

Geometry_XLO float

Geometry_YLO float

Geometry_XHI float

Geometry_YHI float

periodo varchar(1)

Link para o comentário
Compartilhar em outros sites

Olá. Tente isto então se puder ^^

Faça o select primeiramente, e se o retorno estiver OK, é só executar o DELETE. (mas como eu não estou aqui para lhe garantir nada ^^, execute um Start Transaction se o ENGINE for InnoDB para você voltar os dados em caso de erro)

SELECT * FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) FROM Ocorrencias GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

DELETE FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) FROM Ocorrencias GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

Link para o comentário
Compartilhar em outros sites

Olá. Tente isto então se puder ^^

Faça o select primeiramente, e se o retorno estiver OK, é só executar o DELETE. (mas como eu não estou aqui para lhe garantir nada ^^, execute um Start Transaction se o ENGINE for InnoDB para você voltar os dados em caso de erro)

SELECT * FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) FROM Ocorrencias GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

DELETE FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) FROM Ocorrencias GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

O select deu:

Msg 8155, Level 16, State 2, Line 1

No column was specified for column 1 of 'S1'.

Mas eu preciso definir um recorte de tempo, porque tem uma variavel datacriacao.

Link para o comentário
Compartilhar em outros sites

Olá Gustavo, tente agora.

As validações que você necessita, coloque onde está os "TRUE AND TRUE" que coloquei.

DELETE FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) AS ID FROM Ocorrencias WHERE TRUE AND TRUE AND TRUE GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

Link para o comentário
Compartilhar em outros sites

Olá Gustavo, tente agora.

As validações que você necessita, coloque onde está os "TRUE AND TRUE" que coloquei.

DELETE FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) AS ID FROM Ocorrencias WHERE TRUE AND TRUE AND TRUE GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

Msg 4145, Level 15, State 1, Line 3

An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.

Eu tinha entendido o seguinte do SELECT, ele mostraria o MAX(ID) dos registros cujo campo num dão valor superior a 1, ou seja, ele mostraria a linha com maior ID das ocorrencias que tinham num igual, nao é? Porque esse S1? Pelo que entendi, a resposta do select seria uma coluna com nome de S1 onde apareceriam os IDs das linhas da tabela. Eu nao entendi bem o código. A data é onde eu boto no lugar do true, nao é?

Estou fazendo umas esperimentações com as orientações que voce me deu. Eu que estou me enrolando um pouco, se eu tivesse um pouco mais de qualificação, nao estaria no aperto. Eu acabo tendo que aprender na marra. rsrsrsrs

Creio ter obtido resultado desejado, Erciley. Agradeço pelas mensagens de ajuda, elas foram muito úteis. Das 703 linhas duplicadas, com o seu select, ele devolveu 692, mas já até entendi onde errei no meio dos AND, eu preciso completar melhor os parametros para abranger todas as linhas. Vou continuar "brincando" com os parametros e fechar tudo redondinhu pra acabar com esse problema, mas desde já agradeço. Alias, se tiver uma dica de onde eu posso me qualificar melhor pra trabalhar com BD com mais confiança, agradeço imensamente a ajuda.

Link para o comentário
Compartilhar em outros sites

É assim Gustavo:

O Comando DELETE você não pode executar ele fazendo Select na mesma tabela, pois aí iria gerar um outro erro, por isso eu dou o nome de S1 para o select feito na tabela ocorrencias, para aí utilizar o IN para excluir.

Como você executou o comando, da mesma forma que postei? Se foi, é por isso que deu erro, hehehe.

É para você executar "exatamente" o mesmo Select, só que onde está este monte de "TRUE AND TRUE ...." é para você substituir pela condição de datas que você havia falado.

Qual a "Condição Where" que você quer inserir?

Você está usando MySQL?

É para você fazer isso aqui:

DELETE FROM Ocorrencias WHERE ID IN (
SELECT * FROM(
SELECT MAX(ID) AS ID FROM Ocorrencias WHERE datacriacao between "2012/01/01 00:00:00" and "2012/08/31 23:59:59" GROUP BY num HAVING COUNT(*) > 1
) AS S1
);

----------

Complementando:

Estou consultando todos os registros, agrupando pelo campo NUM.

Estou exibindo apenas os registros que o NUM se repita, por isso o COUNT(*) > 1.

Estou fazendo um select externo para enganar o mysql, e com isso renomeio a tabela para S1, virtualmente (mais ou menos isso)

Após essa frescurada toda, faço o delete, onde o campo ID esteja dentro do retorno dessa bagunça toda ^^

Link para o comentário
Compartilhar em outros sites

Mesmo me enrolando, eu consegui entender bem o resultado. Eu, na afobação, rodei as syntaxes e não entendia bem as mensagens de erro. Mas com mais calma eu fui testando, "bricando" pouco a pouco com as condições de recorte dentro dos AND e consegui usar o select pra selecionar as ocorrencias dentro do parametro de data que eu queria e ainda apagar as duplicadas, que era meu objetivo.

Eu só tenho a agradecer pela sua ajuda. Suas orientações foram muito importantes, alias, se souber onde existe algum lugar pra poder me qualificar melhor a mexer com BD com segurança, agradecerei imensamente.

Mas, novamente, muitissimo obrigado.

Respondendo sua pergunta, é um Banco SQL SERVER mesmo, é um banco de dados de produção, ou seja, ta em operação esse "brinquedo". Vacilou, ja viu né, tem que consertar pra ontem, rsrsr Eu tenho backup que eu faço sistematicamente justamente pra nao ficar a pé nessas horas, mas ainda sim, os problemas precisam ser resolvidos, e é na marra que acabo aprendendo. O que me incomoda é não ter uma base sólida pra mexer com isso, sabe.

Link para o comentário
Compartilhar em outros sites

Olá Gustavo.

Até sei aqui no estado de SP alguns lugares para fazer curso, mas não sei se é bom pois nunca fiz. ^^

Outra coisa que eu ia postar e esqueci, é o primeiro select que você postou.

Tente fazer desta forma, acho que melhora a leitura (usando o IN eu digo):

select * from dbo.Ocorrencias 
where tipo_cod IN(307,107,91,114,113,142,412)
and regiao = 23
and datacriacao between '2012/01/01 00:00:00' and '2012/08/31 23:59:59'
order by datacriacao

Bom, é isso aí, que bom que deu certo, abraço.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...