2010-12-08 20 views
1

je voudrais exécuter une instruction SQL qui supprime seulement la deuxième valeur par exemplet-sql - supprimer la deuxième valeur que

delete from table1 where condition1 

Je veux que cette instruction pour supprimer seulement la deuxième valeur

comment puis-je accomplir cela?

Je voudrais clarifier. J'ai un champ appelé field1 qui est un autonumber et et c'est une clé primaire et il s'incrémente. je voudrais supprimer l'enregistrement contenant le plus grand nombre

+0

Comment déterminez-vous quelle valeur vient "en premier" et quelle valeur vient "en second"? –

+2

Est-ce que cela est destiné à nettoyer les entrées en double? C'est en quelque sorte à quoi ça ressemble. – guildsbounty

+0

@anon merci je me suis clarifié –

Répondre

3

Vous pouvez également utiliser la fonction ROW_NUMBER() du serveur SQL pour numéroter chaque ligne et utiliser ce numéro pour isoler uniquement le second élément à supprimer, en fonction de votre propre ordre personnalisé dans la requête interne (over (ORDER BY <myKey> asc)). Cela fournit beaucoup de flexibilité.

DELETE a FROM table1 
FROM table1 a 
JOIN (
     select ROW_NUMBER() over (ORDER BY <myKey> asc) as AutoNumber, <myKey> from table1 
) b on a.<myKey> = b.<myKey> 
WHERE condition1 
AND b.AutoNumber = 2 
+0

La jointure automatique n'est pas nécessaire ici. [Vous pouvez supprimer de la CTE] (http://stackoverflow.com/questions/18932/sql-how-can-i-remove-duplicate-rows/3822833#3822833) –

+0

@Martin: Bon point - J'oublie toujours CTE, parfois la syntaxe peut être assez confuse cependant, cet exemple est plus facile à digérer à mon humble avis. – James

+0

Digest? Vous l'exécutez sans le manger! La suppression du CTE sans l'auto-jointure est plus efficace. –

0

Essayez ceci:

DELETE MyTable 
FROM MyTable 
LEFT OUTER JOIN (
    SELECT MIN(id) as id, Col1, Col2, Col3 
    FROM MyTable 
    GROUP BY Col1, Col2, Col3 
) as KeepRows ON 
    MyTable.id= KeepRows.id 
WHERE 
    KeepRows.RowId IS NULL 

MISE À JOUR

Bien que cela puisse ne pas être aussi « joli » comme @ Jeffrey de cela fonctionne. D'après ce que je peux dire, ce n'est pas le cas de Jeffrey. Voir sql ci-dessous (Supprimer remplacé par SELECT * pour la démonstration):

WITH TEMP as 
(
    SELECT 1 as id,'A' as a,'Z' as b 
    UNION 
    SELECT 2,'A','Z' 
    UNION 
    SELECT 3,'B','Z' 
    UNION 
    SELECT 4,'B','Z' 
) 

SELECT * 
FROM TEMP 
LEFT OUTER JOIN (
    SELECT MIN(id) as id, a, b 
    FROM TEMP 
    GROUP BY a, b 
) as KeepRows ON 
    temp.id= KeepRows.id 
WHERE 
    KeepRows.id IS NULL 
+0

DELETE MyTable FROM MyTable ?? –

+0

Oui. En raison de la jointure. –

+0

Yuk! Utilisez une semi-jointure. –

0

Il a été un certain temps (donc ma syntaxe mon pas tout à fait être à droite), et cela ne peut être la meilleure solution, mais la réponse « académique » Would être quelque chose comme:

delete from table1 where condition1 
and field1 = (select max(field1) from table1 where condition1) 
1

Voulez-vous supprimer uniquement le dernier doublon, ou tous sauf le premier?

Pour tous, mais le premier: (. Sous la direction utiliser CTE par @ suggestion de Martin)

with target as (select * from table1 where condition1) 
delete from target goner 
where exists (select * from target keeper 
       where keeper.field1 < goner.field1) 

En d'autres termes, si un autre enregistrement correspondant à un field1 inférieur, supprimer cet enregistrement.

EDIT: Pour supprimer seulement la dernière:

with target as (select * from table1 where condition1) 
delete from target goner 
where exists (select * from target keeper 
       where keeper.field1 < goner.field1) 
    and not exists (select * from target missing 
        where missing.field1 > goner.field1) 

En d'autres termes, si un autre enregistrement correspondant à un field1 inférieur, et il n'y a pas d'enregistrement correspondant à une field1 plus, nous avoir le plus haut doublon, alors nuke-le.

+0

Je ne pense pas que cela fonctionne.SQL: 'avec la température comme ( SELECT 1 id, 'A' en tant que 'Z' comme b UNION SELECT 2, 'A', 'Z' UNION SELECT 3, 'B', 'Z ' UNION SELECT 4,' B », 'Z' ) SELECT * TEMP de où id> 0 et existe (select * from TEMP autre où other.id> 0 et other.id

+0

Notez qu'il sélectionne 2,3 et 4. –

+0

Yuk! Utilisez un CTE. –