Jump to content


Photo

Registros Iguais


  • Faça o login para participar
15 replies to this topic

#1 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 16/07/2006, 07:27

Opa ... ;)

Lá vem eu com minhas dúvidas complexas ... :D

Imagine uma tabela onde exista 2 campos, A e B. O campo A pode ter valores repetidos, desde que o campo B seja diferente (e vice-versa). Os valores duplicados seriam os que repetirem mais de uma vez um registro com o valor A e B. Confuso ? :unsure:

Partindo desta estrutura, após quebrar a cabeça aqui, consegui consultar todos os registros repetidos e suas respectivas quantidades:

SELECT COUNT(*) AS `quantidade` , `a`, `b` FROM `tabela` GROUP BY `a`, `b` HAVING `quantidade` > 1 ORDER BY `quantidade` DESC
Ok, perfeito. A dúvida é: como excluir os registros iguais ? É possível fazer isso diretamente por uma consulta DELETE ou eu teria de percorrer uma consulta como a acima e excluir separadamente ?

Espero não ter queimado o cérebro de ninguém, já basta o meu ... :P

[]’s :DAté mais

#2 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 16/07/2006, 10:03

Pois é, para trabalhar dessa forma use uma tabela temporária.

Você cria uma tabela temporária com sua query:

CREATE TEMPORARY TABLE testeTmp
SELECT id, COUNT(*) AS `quantidade` , `a`, `b`
FROM teste
GROUP BY `a`, `b`
HAVING `quantidade` > 1
ORDER BY `quantidade` DESC


E a query para deletar usando a tabela temporária:
DELETE FROM teste 
USING testeTmp, teste 
WHERE (teste.a, teste.b) = (testeTmp.a, testeTmp.b) AND teste.id <> testeTmp.id

Não sei se você já leu sobre as tabelas temporárias, desde então deixo uma parte do texto do manual:

A partir do MySQL Versão 3.23, você pode usar a palavra-chave TEMPORARY qaundo você criar uma tabela. A tabela temporária é visível apenas a para a conexão atual, e será automaticamente deletada quando a conexão é fechada. Isto significa que duas conexões diferentes podem usar o mesmo nome de tabela temporária sem conflitos outras ou com uma tabela existente com o mesmo nome. (A tabela existente é escondida até que a tabela temporária seja deletada). A partir do MySQL 4.0.2 você deve ter o privilégio CREATE TEMPORARY TABLES para poder criar tabelas temporárias.


Edição feita por: Eclesiastes, 16/07/2006, 10:05.

Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#3 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 16/07/2006, 10:54

Pois é, para trabalhar dessa forma use uma tabela temporária.

Você cria uma tabela temporária com sua query:

CREATE TEMPORARY TABLE testeTmp
SELECT id, COUNT(*) AS `quantidade` , `a`, `b`
FROM teste
GROUP BY `a`, `b`
HAVING `quantidade` > 1
ORDER BY `quantidade` DESC


E a query para deletar usando a tabela temporária:
DELETE FROM teste 
USING testeTmp, teste 
WHERE (teste.a, teste.b) = (testeTmp.a, testeTmp.b) AND teste.id <> testeTmp.id

Não sei se você já leu sobre as tabelas temporárias, desde então deixo uma parte do texto do manual:

A partir do MySQL Versão 3.23, você pode usar a palavra-chave TEMPORARY qaundo você criar uma tabela. A tabela temporária é visível apenas a para a conexão atual, e será automaticamente deletada quando a conexão é fechada. Isto significa que duas conexões diferentes podem usar o mesmo nome de tabela temporária sem conflitos outras ou com uma tabela existente com o mesmo nome. (A tabela existente é escondida até que a tabela temporária seja deletada). A partir do MySQL 4.0.2 você deve ter o privilégio CREATE TEMPORARY TABLES para poder criar tabelas temporárias.

Opa ... ;)

Uai ! Tu acaba de salvar uma vida ! :P

Valeu mesmo, obrigadão ! :D

Não havia lido sobre tabelas temporárias ainda, aliás, pouco sei de MySQL, he he. :unsure:

Funcionou na mais perfeita maravilha ! :D

Tipo, nesta consulta:

DELETE FROM teste 
USING testeTmp, teste 
WHERE (teste.a, teste.b) = (testeTmp.a, testeTmp.b) AND teste.id <> testeTmp.id
Tu usou um pseudo-campo id, para remover pelo identificador. Supondo que haja só os campos A e B, não teria como eu deletar tudo de uma vez em uma só query ?

Eu nem cheguei à executar esta query...

DELETE FROM teste 
USING testeTmp, teste 
WHERE (teste.a, teste.b) = (testeTmp.a, testeTmp.b)
... pois logo me liguei que ela removeria além dos registros duplicados, os registros únicos que tiveram duplicidade. Que confusão ... *rs* :P

Teria como ?! :ponder:

[]’s :DAté mais

#4 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 16/07/2006, 12:10

Hhehhehe, pois bem, eu coloquei o:

teste.id <> testeTmp.id


Para deixar o registro 'original' na tabela, ou melhor, a primeira ocorrência do registro repetido, e apagar somente os registros que vieram após ele, tornando-o repetido na tabela.

Eu coloquei isso por que não entendi a intenção, se era para apagar da tabela todos os registros que se encontram repetidos, ou se era para apagar somente os registros que tornaram um registro repetido.
Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#5 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 17/07/2006, 01:04

Hhehhehe, pois bem, eu coloquei o:

teste.id <> testeTmp.id


Para deixar o registro 'original' na tabela, ou melhor, a primeira ocorrência do registro repetido, e apagar somente os registros que vieram após ele, tornando-o repetido na tabela.

Eu coloquei isso por que não entendi a intenção, se era para apagar da tabela todos os registros que se encontram repetidos, ou se era para apagar somente os registros que tornaram um registro repetido.

Ah ... saquei ! :D

O propósito era apagar somente os registros que tornaram um registro repetido, he he. Como só existem etes 2 campos, não tenho idéia do que posso fazer. :ponder:

Teria solução ? Se não tiver eu adiciono um campo de auto-incremento e já era... :P

Valeu denovo ! =)

[]’s :DAté mais

#6 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 17/07/2006, 09:57

Pois é, não vejo outra saída. (y)
Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#7 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 17/07/2006, 13:16

Pois é, não vejo outra saída. (y)

Opa ... ;)

Valeu, funcionou perfeitamente ! =)

Antes o BD tinha 9.587 registros. Efetuei esta consulta para saber quantos registros deveria restar:

SELECT DISTINCT `a`, `b` FROM `tabela`
Deu 5.975. Executei as duas consultas que tu me indicou e restou apenas os 5.975 registros, ou seja, perfeito, hehe ! :aplauder:

Agora vou modificar uma parte do código para não inserir caso já haja algum registro com o mesmo valor de A e B. =)

Valeu denovo ! :D

[]’s :DAté mais

#8 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 23/07/2006, 15:26

Agora vou modificar uma parte do código para não inserir caso já haja algum registro com o mesmo valor de A e B. =)

Cá estou eu novamente. :P

Conforme o que citei acima, me surgiu uma dúvida... seria possível fazer esta verificação logo no INSERT ? :ponder:

Tipo, deixa eu explicar melhor. A tabela tem apenas 2 campos: A e B. Pode haver registros repetidos tanto em A como B desde o valor de A ou B (dependendo do caso) ainda não tenha.

Confuso ? :P

Deixa eu tentar exemplificar:

Campo A	 Campo B
Laranja	 Limão
Laranja	 Maçã
Limão	   Laranja
Maçã		Laranja
Ou seja, se já tiver um registro com Laranja em A e [i]Limão[/b] em B, não insere. :)

À partir da simples inserção...

INSERT INTO `tabela` (`a`, `b`) VALUES ('Laranja', 'Limão');
...eu poderia fazer esta verificação logo nela ? :unsure:

É, acho que além de me confundir, compliquei a história. :P

[]’s :DAté mais

#9 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 23/07/2006, 16:51

Sim, entendi. Pois então, utilize a propriedade UNIQUE nas duas colunas.

Se estiver usando PHP, a função mysql_errno() irá retornar o númerro 1062 (se não estou enganado), indicando assim, que estás tentando duplicar um registro. E como no caso as duas colunas são UNIQUE, o aviso/erro ao inserir só será enviado caso tente duplicar um registro, ou melhor, onde se encontra os dois valores na mesma linha.
Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#10 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 23/07/2006, 20:35

Sim, entendi. Pois então, utilize a propriedade UNIQUE nas duas colunas.

Se estiver usando PHP, a função mysql_errno() irá retornar o número 1062 (se não estou enganado), indicando assim, que estás tentando duplicar um registro. E como no caso as duas colunas são UNIQUE, o aviso/erro ao inserir só será enviado caso tente duplicar um registro, ou melhor, onde se encontra os dois valores na mesma linha.

Mas, tipo... sendo os 2 campos UNIQUE, não será permitida a inserção de Laranja {A} e Limão {B} se já houver Laranja {A} e Maçã {B}, ou estou errado ? :unsure:

Resumindo o que eu havia dito no post passado, é para não pertimir registros iguais, onde A e B terão o mesmo valor de um registro já existente. Pronto, resumi tudo o que compliquei, rs. :P

[]’s :DAté mais

#11 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 23/07/2006, 22:48

Foi justamente isso que quis dizer, mas confesso que me embolei. :P

Se existe:
Laranja | Limão

Irá permitir:
Limão | Laranja
Laranja | Uva
Uva | Laranja

Não irá permitir:
Laranja | Limão

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

Existe também este recurso:

Se você especificar a palavra-chave IGNORE em um INSERT com muitas linhas, qualquer linha que duplicar uma chave PRIMARY ou UNIQUE existente em uma tabela são ignorados e não são inseridos. Se você não especificar IGNORE, a inserção é abortada se houver quqlquer linhq que duplique um valor de uma chave existente.


Ficaria então:
INSERT IGNORE INTO ...

Edição feita por: Eclesiastes, 23/07/2006, 23:48.

Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#12 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 24/07/2006, 12:41

Foi justamente isso que quis dizer, mas confesso que me embolei. :P

Se existe:

Laranja | Limão

Irá permitir:
Limão | Laranja
Laranja | Uva
Uva | Laranja

Não irá permitir:
Laranja | Limão

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

Existe também este recurso:

Se você especificar a palavra-chave IGNORE em um INSERT com muitas linhas, qualquer linha que duplicar uma chave PRIMARY ou UNIQUE existente em uma tabela são ignorados e não são inseridos. Se você não especificar IGNORE, a inserção é abortada se houver quqlquer linhq que duplique um valor de uma chave existente.


Ficaria então:
INSERT IGNORE INTO ...

Nossa ! :o

Eu jurava que UNIQUE não era isso, rs. Tá vendo, eu disse, preciso continuar apreendendo SQL / MySQL por um bom tempo (rs) ! :P

Com esse IGNORE então, maravilha, he he ! Preciso ler o manual do MySQL com mais frequência... :P

Valeu denovo ! ;)

Edição

Mas... aconteceu o que eu disse. Deixando os campos UNIQUE eles não permitem que tenha mais de um campo A (por exemplo) com o mesmo valor, mesmo que o B deles seja diferente. Entende ? :(

[]’s :DAté mais

#13 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 24/07/2006, 15:23

Ué! Criei uma tabela com campos A e B como UNIQUE.

E consegui registrar:

a | b
a | c
a | d


E ao tentar duplicar um registro recebo o aviso:

Duplicate entry 'a-c' for key 2


Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29

#14 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 24/07/2006, 16:02

Ué! Criei uma tabela com campos A e B como UNIQUE.

E consegui registrar:

a | b
a | c
a | d


E ao tentar duplicar um registro recebo o aviso:

Duplicate entry 'a-c' for key 2

Uai ! :blink:

Primeiro, fiz aquela parada do início do tópico, deixei só os registros únicos. Depois, quando fui adicionar o UNIQUE aos campos, deu o erro Duplicate entry 'valor_do_campo' for key 2. :unsure:

Agora quem não entendeu fui eu ! :lol:

PS: Lembrando que, o campo ID com auto-incremento foi inserido, para funcionar a consulta do começo. Porém, acredito que ele não interfira em nada, né ? =)

[]’s :DAté mais

#15 Felipe Pena

Felipe Pena

    O temor do Senhor é o princípio da sabedoria

  • Ex-Admins
  • 6441 posts
  • Sexo:Masculino

Posted 24/07/2006, 17:37

Ah certo! Compreendi. O erro está na hora de criar, pois está sendo feita uma checagem na hora de criar o UNIQUE para cada campo.

Por exemplo, tem os seguintes registros:

a | b
a | c


Ao usar o comando:
ALTER TABLE `tabela` ADD UNIQUE (a), ADD UNIQUE (b)

Ele tentará criar o UNIQUE para o campo a primeiramente, e sendo assim, ele irá constar que existe valores duplicados para esta coluna.

É isso que está acontecendo! :(

Bom, pelo que eu li não há jeito de mudar o modo em que funciona o ALTER TABLE, ele só contém o IGNORE, mas serve apenas para não emitir o erro, como vimos no comando INSERT.

Enfim, como no caso há valores repetidos em 1 coluna, acho que só recriando a tabela e inserindo os dados.

Daí para inserir você poderia usar a sintaxe INSERT ... SELECT.

Exemplo:
INSERT teste2 (id, a, b) SELECT id, a, b FROM teste

(y)

Edição feita por: Eclesiastes, 24/07/2006, 17:39.

Felipe Pena
[...] ó terra, terra, terra; ouve a palavra do Senhor. — Jeremias 22:29




0 user(s) are reading this topic

0 membro(s), 0 visitante(s) e 0 membros anônimo(s)

IPB Skin By Virteq