Duplicate possible:
SQL - Comment puis-je supprimer les lignes en double?
J'ai une table avec une très grande quantité de lignes. Les doublons ne sont pas autorisés, mais en raison d'un problème de création des lignes, je sais qu'il y a des doublons dans ce tableau. Je dois éliminer les lignes supplémentaires du point de vue des colonnes clés. Certaines autres colonnes peuvent avoir légèrement des données différentes, mais cela ne me dérange pas. J'ai encore besoin de garder une de ces lignes cependant. SELECT DISTINCT ne fonctionnera pas car il fonctionne sur toutes les colonnes et je dois supprimer les doublons en fonction des colonnes de clé.
Comment puis-je supprimer les lignes supplémentaires tout en en conservant une efficacement?
Vous n'avez pas indiqué la version que vous utilisiez, mais dans SQL 2005 et versions ultérieures, vous pouvez utiliser une expression de table commune avec la clause OVER . C'est un peu comme ça:
WITH cte AS (
SELECT[foo], [bar],
row_number() OVER(PARTITION BY foo, bar ORDER BY baz) AS [rn]
FROM TABLE
)
DELETE cte WHERE [rn] > 1
Jouez avec et voyez ce que vous obtenez.
(Édition: pour tenter de vous aider, quelqu'un a édité la clause ORDER BY
dans le CTE. Pour être clair, vous pouvez commander par tout ce que vous voulez ici, il ne doit pas nécessairement s'agir d'une des colonnes renvoyées par le cte. En fait, un cas d'utilisation courant ici est que "foo, bar" est l'identifiant du groupe et "baz" est une sorte d'horodatage. Pour conserver les dernières informations, vous feriez ORDER BY baz desc
)
Exemple de requête:
DELETE FROM Table
WHERE ID NOT IN
(
SELECT MIN(ID)
FROM Table
GROUP BY Field1, Field2, Field3, ...
)
Ici, fields
sont des colonnes sur lesquelles vous souhaitez regrouper les lignes en double.
Voici ma version, avec un exemple exploitable. Note Cela ne fonctionnera que dans la situation où Id
est unique et que vous avez des valeurs en double dans d'autres colonnes.
DECLARE @SampleData AS TABLE (Id int, Duplicate varchar(20))
INSERT INTO @SampleData
SELECT 1, 'ABC' UNION ALL
SELECT 2, 'ABC' UNION ALL
SELECT 3, 'LMN' UNION ALL
SELECT 4, 'XYZ' UNION ALL
SELECT 5, 'XYZ'
DELETE FROM @SampleData WHERE Id IN (
SELECT Id FROM (
SELECT
Id
,ROW_NUMBER() OVER (PARTITION BY [Duplicate] ORDER BY Id) AS [ItemNumber]
-- Change the partition columns to include the ones that make the row distinct
FROM
@SampleData
) a WHERE ItemNumber > 1 -- Keep only the first unique item
)
SELECT * FROM @SampleData
Et les résultats:
Id Duplicate
----------- ---------
1 ABC
3 LMN
4 XYZ
Je ne sais pas pourquoi c'est ce que je pensais d'abord… Ce n'est certainement pas la solution la plus simple, mais cela fonctionne.