MariaDB
 sql >> Base de données >  >> RDS >> MariaDB

7 façons de renvoyer des lignes en double qui ont une clé primaire dans MariaDB

Voici sept façons de renvoyer des lignes en double dans MariaDB lorsque ces lignes ont une clé primaire ou une autre colonne d'identifiant unique.

Par conséquent, les lignes en double partagent exactement les mêmes valeurs dans toutes les colonnes, à l'exception de leur colonne d'identifiant unique.

Exemple de données

Nous utiliserons les données suivantes pour nos exemples :

SELECT * FROM Dogs;

Résultat :

+-------+-----------+----------+
| DogId | FirstName | LastName |
+-------+-----------+----------+
|     1 | Bark      | Smith    |
|     2 | Bark      | Smith    |
|     3 | Woof      | Jones    |
|     4 | Ruff      | Robinson |
|     5 | Wag       | Johnson  |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Les deux premières lignes sont des doublons (sauf pour le DogId colonne, qui est la clé primaire de la table et contient une valeur unique sur toutes les lignes). Les trois dernières lignes sont également des doublons (sauf pour le DogId colonne).

La colonne de clé primaire garantit qu'il n'y a pas de lignes en double, ce qui est normalement une bonne chose dans les SGBDR. Cependant, par définition, cela signifie qu'il n'y a pas de doublons. Dans notre cas, la colonne de la clé primaire est un nombre qui s'incrémente, et sa valeur n'a aucune signification et n'est pas significative. Nous devons donc ignorer cette ligne si nous voulons trouver des doublons dans les colonnes qui sont important.

Option 1

Nous pouvons utiliser le GROUP BY clause pour regrouper les colonnes par leurs colonnes significatives, puis utilisez le COUNT() fonction pour retourner le nombre de lignes identiques :

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;

Résultat :

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Ruff      | Robinson |     1 |
| Wag       | Johnson  |     3 |
| Woof      | Jones    |     1 |
+-----------+----------+-------+

Nous avons pu exclure la colonne de clé primaire en l'omettant de notre requête.

Le résultat nous indique qu'il y a deux lignes contenant Bark Smith et trois lignes contenant Wag Johnson. Ce sont des doublons (ou des triples dans le cas de Wag Johnson). Les deux autres lignes n'ont pas de doublons.

Option 2

Nous pouvons exclure les non-doublons de la sortie avec le HAVING clause :

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;

Résultat :

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Option 3

Il est également possible de vérifier les doublons sur les colonnes concaténées. Par exemple, nous pouvons utiliser le CONCAT() fonction pour concaténer nos deux colonnes, utilisez le DISTINCT mot-clé pour obtenir des valeurs distinctes, puis utilisez le COUNT() fonction pour retourner le compte :

SELECT
    DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);

Résultat :

+---------------+-------+
| DogName       | Count |
+---------------+-------+
| Bark Smith    |     2 |
| Ruff Robinson |     1 |
| Wag Johnson   |     3 |
| Woof Jones    |     1 |
+---------------+-------+

Option 4

Nous pouvons utiliser le ROW_NUMBER() fonction avec le PARTITION BY clause :

SELECT 
    *,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS Row_Number
FROM Dogs;

Résultat :

+-------+-----------+----------+------------+
| DogId | FirstName | LastName | Row_Number |
+-------+-----------+----------+------------+
|     1 | Bark      | Smith    |          1 |
|     2 | Bark      | Smith    |          2 |
|     4 | Ruff      | Robinson |          1 |
|     6 | Wag       | Johnson  |          1 |
|     5 | Wag       | Johnson  |          2 |
|     7 | Wag       | Johnson  |          3 |
|     3 | Woof      | Jones    |          1 |
+-------+-----------+----------+------------+

Cela crée une nouvelle colonne avec un numéro de ligne qui s'incrémente à chaque fois qu'il y a un doublon, mais se réinitialise à nouveau lorsqu'il y a une ligne unique.

Dans ce cas, nous ne regroupons pas les résultats, ce qui signifie que nous pouvons voir chaque ligne en double, y compris sa colonne d'identifiant unique.

Option 5

Nous pouvons également utiliser l'exemple précédent comme expression de table commune dans une requête plus large :

WITH cte AS 
    (
        SELECT 
            *,
            ROW_NUMBER() OVER ( 
                PARTITION BY FirstName, LastName 
                ORDER BY FirstName, LastName
                ) AS Row_Number
        FROM Dogs
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Résultat :

+-------+-----------+----------+------------+
| DogId | FirstName | LastName | Row_Number |
+-------+-----------+----------+------------+
|     2 | Bark      | Smith    |          2 |
|     5 | Wag       | Johnson  |          2 |
|     7 | Wag       | Johnson  |          3 |
+-------+-----------+----------+------------+

Cela exclut les non-doublons de la sortie et exclut une ligne de chaque doublon de la sortie.

Cette requête pourrait être utilisée comme précurseur d'une opération de dédoublonnage. Il peut nous montrer ce qui va être supprimé si nous décidons de supprimer les doublons. Pour dédupliquer la table, il suffit de remplacer le dernier SELECT * avec DELETE .

Option 6

Voici une manière plus succincte d'obtenir le même résultat que dans l'exemple précédent :

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

Résultat :

+-------+-----------+----------+
| DogId | FirstName | LastName |
+-------+-----------+----------+
|     2 | Bark      | Smith    |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Cet exemple ne nécessite pas de générer notre propre numéro de ligne séparé.

Nous pouvons remplacer SELECT * avec DELETE pour supprimer les doublons.

Option 7

Et enfin, voici une autre option pour renvoyer les doublons :

SELECT * 
FROM Dogs d1, Dogs d2 
WHERE d1.FirstName = d2.FirstName 
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId 
AND d1.DogId = (
    SELECT MAX(DogId) 
    FROM Dogs d3 
    WHERE d3.FirstName = d1.FirstName 
    AND d3.LastName = d1.LastName
);

Résultat :

+-------+-----------+----------+-------+-----------+----------+
| DogId | FirstName | LastName | DogId | FirstName | LastName |
+-------+-----------+----------+-------+-----------+----------+
|     2 | Bark      | Smith    |     1 | Bark      | Smith    |
|     7 | Wag       | Johnson  |     5 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |     6 | Wag       | Johnson  |
+-------+-----------+----------+-------+-----------+----------+