Voici quatre méthodes que vous pouvez utiliser pour rechercher des lignes en double dans SQL Server.
Par "lignes en double", j'entends deux lignes ou plus qui partagent exactement les mêmes valeurs dans toutes les colonnes.
Exemple de données
Supposons que nous ayons un tableau avec les données suivantes :
SELECT * FROM Pets;
Résultat :
+---------+-----------+-----------+ | PetId | PetName | PetType | |---------+-----------+-----------| | 1 | Wag | Dog | | 1 | Wag | Dog | | 2 | Scratch | Cat | | 3 | Tweet | Bird | | 4 | Bark | Dog | | 4 | Bark | Dog | | 4 | Bark | Dog | +---------+-----------+-----------+
Nous pouvons voir que les deux premières lignes sont des doublons, tout comme les trois dernières lignes.
Option 1
Nous pouvons utiliser la requête suivante pour renvoyer des informations sur les lignes en double :
SELECT
DISTINCT PetId,
COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;
Résultat :
+---------+---------+ | PetId | Count | |---------+---------| | 1 | 2 | | 2 | 1 | | 3 | 1 | | 4 | 3 | +---------+---------+
Nous pouvons développer le SELECT
list pour inclure plus de colonnes si nécessaire :
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Résultat :
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+
Si la table a un identifiant unique, nous pouvons simplement supprimer cette colonne de la requête. Par exemple, si nous supposons que le PetId
est en fait une colonne de clé primaire contenant un identifiant unique, nous pourrions exécuter la requête suivante pour renvoyer toutes les lignes qui sont des doublons, sans compter la colonne de clé primaire :
SELECT
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetName,
PetType
ORDER BY PetName;
Résultat :
+-----------+-----------+---------+ | PetName | PetType | Count | |-----------+-----------+---------| | Bark | Dog | 3 | | Scratch | Cat | 1 | | Tweet | Bird | 1 | | Wag | Dog | 2 | +-----------+-----------+---------+
Option 2
Si nous voulons que seules les lignes en double réelles soient renvoyées, nous pouvons ajouter le HAVING
clause :
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY PetId;
Résultat :
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+
Option 3
Une autre façon de le faire est d'utiliser le ROW_NUMBER()
fonction avec le PARTITION BY
clause pour numéroter la sortie du jeu de résultats.
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Résultat :
+---------+-----------+-----------+--------------+ | PetId | PetName | PetType | Row_Number | |---------+-----------+-----------+--------------| | 1 | Wag | Dog | 1 | | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 1 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+--------------+
La PARTITION BY
la clause divise le jeu de résultats produit par le FROM
clause en partitions auxquelles la fonction est appliquée. Lorsque nous spécifions des partitions pour le jeu de résultats, chaque partition fait recommencer la numérotation (c'est-à-dire que la numérotation commencera à 1 pour la première ligne de chaque partition).
Option 4
Si nous voulons que seules les lignes excédentaires des doublons correspondants soient renvoyées, nous pouvons utiliser la requête ci-dessus comme expression de table commune, comme ceci :
WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets
)
SELECT * FROM CTE WHERE Row_Number <> 1;
Résultat :
+---------+-----------+-----------+--------------+ | PetId | PetName | PetType | Row_Number | |---------+-----------+-----------+--------------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+--------------+
L'un des avantages de cette opération est que nous pouvons supprimer les lignes en double simplement en changeant SELECT *
pour DELETE
(sur la dernière ligne).
Par conséquent, nous pouvons utiliser le code ci-dessus pour voir quelles lignes seront supprimées, puis lorsque nous sommes convaincus que nous allons supprimer les lignes correctes, nous pouvons le remplacer par un DELETE
pour les supprimer réellement.
Comme ceci :
WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets
)
DELETE FROM CTE WHERE Row_Number <> 1;