2011-06-27 3 views
1

J'ai un tableau PEOPLE, avec les colonnes 'firstName' 'lastName' (varchars) et 'deleted' (bit) parmi d'autres.MySQL DELETE requête avec conditions

Je souhaite supprimer de cette table les entrées qui ont la propriété TRUE pour supprimé, mais uniquement si elles partagent leur prénom exact et leur nom de famille avec une autre entrée distincte dans la table. En d'autres termes, supprimez de la table les personnes 'supprimées', mais uniquement s'il s'agit d'un doublon.

Vous ne savez pas comment faire cela, et surtout pas comment le faire rapidement. Toute aide est appréciée, merci.

+0

Comment savoir quel est le double et quel est le premier enregistrement? –

+0

duplication possible de [Duplicate Entries in DB] (http://stackoverflow.com/questions/5970329/duplicate-entries-in-db) – Neal

+0

Tous les champs sont dans la même table? –

Répondre

1
DELETE FROM people 
WHERE EXISTS (
    SELECT * 
    FROM people p2 
    WHERE people.firstName = p2.firstName AND people.lastName = p2.lastName 
    GROUP BY firstName, lastName 
    HAVING COUNT(*)>1 
) 
AND deleted = 1 -- True 
+0

avez-vous besoin de la clause where dans l'instruction imbriquée? – Dirk

+0

Oui, pour joindre la sous-requête à la table externe. – niktrs

+0

@niktrs, cela prendra un temps loooong est la table est énorme. – Neal

1

Si votre table a une clé primaire unique (... dépendra de la conception ...), alors c'est une alternative viable à avoir besoin de compter les occurences d'entrées:

DELETE FROM people as A 
WHERE deleted = 1 
AND EXISTS (SELECT '1' 
      FROM people as B 
      WHERE B.id <> A.id 
      AND A.firstName = B.firstName 
      AND A.lastName = B.lastName) 

Cela peut avoir des performances légèrement meilleures que le comptage des lignes. S'il vous plaît noter que cette requête souffrira probablement le même problème possible présent dans la réponse précédente; en particulier, s'il y a deux ou plusieurs lignes «supprimées», et aucune «non supprimée», les deux seront probablement supprimées (vous laissant sans lignes!). Si l'intention de la requête est uniquement de supprimer les lignes "supprimées" lorsqu'il existe une ligne équivalente "non supprimée", ajoutez AND B.deleted = 0 dans la clause interne WHERE.

+0

Génial - celui-ci permet un correctif facile 'AND B.deleted = 0' que je soupçonne que le questionneur veut, où l'autre ne le veut pas. –

+0

Suggestion: Utilisez A.id> B.id, de sorte que tout ce qui est plus récent que le premier enregistrement sera supprimé. Fonctionne aussi plus vite. – niktrs

+0

@niktrs - Malheureusement, cela présume que seuls les identifiants plus récents (ou plus anciens) sont «supprimés». Selon la conception et l'utilisation, cette hypothèse peut être valide ou non. Mais oui, sinon, cela fonctionnerait probablement mieux. –