[php/mysql] dubbele rijen verwijderen

Pagina: 1
Acties:
  • 204 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb een MySQL-database met persoonsgegevens (voornaam, achternaam, geboortedatum, etc.), deze wordt constant gevuld door input van diverse websites.

In de nacht draaien cronjobs en nu moet er een bijkomen; de dubbele (hierbij wordt een vergelijking getrokken door te kijken naar de waarden in de velden voornaam, achternaam en geboortedatum) rijen moeten worden verwijderd. Deze vergelijking is overigens door de opdrachtgever bepaald, dus niet discutabel. Ik heb er eens over nagedacht, maar ik zou zo een-twee-drie niet weten hoe ik rijen selecteer (en vervolgens- of direct verwijder) die dubbel aanwezig zijn conform de voorwaarden.

En daarbij, kan ik een voorwaarde stellen aan de rij die verwijderd moet worden? Dus, verwijder de laatst-toegevoegde bijvoorbeeld.

Naar aanleiding van een zoekactie hier op GoT kwam ik erachter dat je tevens een unique kunt toevoegen aan de MySQL-tabel, maar dit is helaas niet mogelijk in mijn situatie. Het toevoegen mag namelijk best in eerste instantie, maar zoals gemeld worden 's nachts automatisch de dubbele rijen verwijderd.

[ Voor 20% gewijzigd door Verwijderd op 18-11-2005 16:00 ]


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

DELETE FROM je_tabel t1, je_tabel t2 WHERE t1.voornaam=t2.voornaam AND t1.achternaam=t2.achternaam AND t1.geboortedatum=t2.geboortedatum

Zou zoiets niet werken? Tijdje geleden dat ik SQL heb gedaan.

Acties:
  • 0 Henk 'm!

  • Reinier
  • Registratie: Februari 2000
  • Laatst online: 23:40

Reinier

\o/

Je zegt dat het niet discutabel is, maar toch: weet je heel erg zeker dat die selectiecriteria correct zijn? Een persoon is immers niet uniek te identificeren a.d.h.v. voornaam, achternaam en geboortedatum.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 22:34
prototype schreef op vrijdag 18 november 2005 @ 16:00:
DELETE FROM je_tabel t1, je_tabel t2 WHERE t1.voornaam=t2.voornaam AND t1.achternaam=t2.achternaam AND t1.geboortedatum=t2.geboortedatum
Zou zoiets niet werken? Tijdje geleden dat ik SQL heb gedaan.
Als het al werkt, dan delete je al je records :X

[ Voor 20% gewijzigd door T-MOB op 18-11-2005 16:09 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Reinier
  • Registratie: Februari 2000
  • Laatst online: 23:40

Reinier

\o/

Wat je ook kan doen:

• Maak een tijdelijke tabel #tmp aan
• Vul deze a.d.h.v. een SELECT DISTINCT voornaam , achternaam , etc. query
• Truncate je oorspronkelijke tabel
• Pomp de data uit #tmp terug naar je oorspronkelijke tabel
• Verwijder #tmp

Het kan vast mooier en misschien ook veiliger, maar het werkt wel :)

Acties:
  • 0 Henk 'm!

  • pierre-oord
  • Registratie: April 2002
  • Laatst online: 10-02 23:00
Nog simpeler: kijk gewoon bij het invoegen of het veld al bestaat? Dan pak je het probleem bij de bron aan.

Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

T-MOB schreef op vrijdag 18 november 2005 @ 16:09:
[...]

Als het al werkt, dan delete je al je records :X
Doh :X :'(

[ Voor 64% gewijzigd door prototype op 18-11-2005 16:22 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Het is een beetje afhankelijk van de grootte van de tabel en de hoeveelheid dubbelen. Als die verhouding vooral zeer sterk naar de eerste leunt dan kun je beter niet de door reinier voorgestelde methode gebruiken. Eventueel kun je met een group by, count en having een query genereren van alle namen die dubbel voorkomen. Deze kun je dan 'programmatisch' verwijderen.

Ik ben er trouwens al wel achter dat er van mijn naam en geboortedatum iig nog iemand rondloopt. Daar ben ik via het ziekenhuis en via een sofinummer conflict achter gekomen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 22:34
prototype schreef op vrijdag 18 november 2005 @ 16:20:
[...]

Doh :X :'(
Ik weet niet of er sprake is van misschien een ID, maar dan zou je nog bij de where clausule dus kunnen toevoegen, dat de ID's niet overeen mogen komen.
Je moet er idd een ander veld bijhalen, waarin je gelijk de voorwaarde kunt vastleggen. Alleen controleren op ongelijkheid haalt namelijk alsnog alle records weg waarvan er dubbelen in de database voorkomen. Als er sprake is van een id, waarbij een nieuwer record altijd een hoger id heeft dan ouder record kun je met iets als onderstaande de laatst toegevoegde ID's laten zien:
code:
1
2
3
4
5
6
7
8
SELECT t.id
FROM table as t
INNER JOIN table as t2 ON (
    t.naam = t2.naam 
    AND t.voornaam = t2.voornaam 
    AND t.birth = t2.birth
    AND t.id > t2.id
    )

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
Bij MySQL kun je in plaats van INSERT de methode REPLACE gebruiken. Daarbij wordt eerst gegeken of een rij al bestaat met die gegevens, en wordt aangemaakt als die nog niet bestaat en geupdate als 'ie wel bestaat :) Zo heb je in principe geen dubbele rijen als je het een beetje slim aanpakt :)

En je kunt de dubbele rijen eventueel selecteren met (uit m'n hoofd, untested):

SQL:
1
SELECT id, COUNT(tabeltwee.id) AS aantalaanwezig FROM tabel LEFT JOIN tabel AS tabeltwee ON tabel.veld=tabeltwee.veld GROUP BY tabel.id HAVING aantalaanwezig>1;


Of iets in die richting...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
T-MOB schreef op vrijdag 18 november 2005 @ 16:27:
[...]


Je moet er idd een ander veld bijhalen, waarin je gelijk de voorwaarde kunt vastleggen. Alleen controleren op ongelijkheid haalt namelijk alsnog alle records weg waarvan er dubbelen in de database voorkomen. Als er sprake is van een id, waarbij een nieuwer record altijd een hoger id heeft dan ouder record kun je met iets als onderstaande de laatst toegevoegde ID's laten zien:
code:
1
2
3
4
5
6
7
8
SELECT t.id
FROM table as t
INNER JOIN table as t2 ON (
    t.naam = t2.naam 
    AND t.voornaam = t2.voornaam 
    AND t.birth = t2.birth
    AND t.id > t2.id
    )
Briljant, dit zocht ik. Mijn dank is groot... Gegroet!

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Het volgende linkje is wel relevant binnen dit topic:
http://www.nu.nl/news/629..._geboorte_baby_Sofie.html

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Reinier
  • Registratie: Februari 2000
  • Laatst online: 23:40

Reinier

\o/

Dit topic was het eerste waar ik aan dacht toen ik dat bericht las :)
Pagina: 1