sql >> Database teknologi >  >> RDS >> MariaDB

7 måder at returnere duplikerede rækker, der har en primær nøgle i MariaDB

Her er syv måder at returnere duplikerede rækker i MariaDB, når disse rækker har en primærnøgle eller anden unik identifikatorkolonne.

Derfor deler de duplikerede rækker nøjagtig de samme værdier på tværs af alle kolonner undtagen deres unikke identifikatorkolonne.

Eksempel på data

Vi bruger følgende data til vores eksempler:

SELECT * FROM Dogs;

Resultat:

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

De første to rækker er dubletter (undtagen DogId kolonne, som er tabellens primære nøgle og indeholder en unik værdi på tværs af alle rækker). De sidste tre rækker er også dubletter (bortset fra DogId kolonne).

Den primære nøglekolonne sikrer, at der ikke er nogen duplikerede rækker, hvilket normalt er en god ting i RDBMS'er. Men per definition betyder dette, at der ikke er nogen dubletter. I vores tilfælde er den primære nøglekolonne et stigende tal, og dens værdi har ingen betydning og er ikke signifikant. Vi er derfor nødt til at ignorere den række, hvis vi vil finde dubletter i de kolonner, der er væsentlig.

Mulighed 1

Vi kan bruge GROUP BY klausul for at gruppere kolonnerne efter deres signifikante kolonner, og brug derefter den COUNT() funktion for at returnere antallet af identiske rækker:

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

Resultat:

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

Vi var i stand til at ekskludere den primære nøglekolonne ved at udelade den fra vores forespørgsel.

Resultatet fortæller os, at der er to rækker indeholdende Bark Smith og tre rækker indeholdende Wag Johnson. Disse er dubletter (eller triplikater i tilfældet med Wag Johnson). De to andre rækker har ingen dubletter.

Mulighed 2

Vi kan ekskludere ikke-duplikater fra outputtet med HAVING klausul:

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

Resultat:

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

Mulighed 3

Det er også muligt at kontrollere for dubletter på sammenkædede kolonner. For eksempel kan vi bruge CONCAT() funktion til at sammenkæde vores to kolonner, brug DISTINCT søgeord for at få forskellige værdier, og brug derefter COUNT() funktion for at returnere antallet:

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

Resultat:

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

Mulighed 4

Vi kan bruge ROW_NUMBER() funktion med PARTITION BY klausul:

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

Resultat:

+-------+-----------+----------+------------+
| 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 |
+-------+-----------+----------+------------+

Dette opretter en ny kolonne med et rækkenummer, der stiger, hver gang der er en dublet, men nulstilles igen, når der er en unik række.

I dette tilfælde grupperer vi ikke resultaterne, hvilket betyder, at vi kan se hver dubletrække, inklusive dens unikke identifikatorkolonne.

Mulighed 5

Vi kan også bruge det forrige eksempel som et almindeligt tabeludtryk i en større forespørgsel:

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;

Resultat:

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

Dette udelukker ikke-duplikater fra outputtet, og det udelukker en række af hver dublet fra outputtet.

Denne forespørgsel kunne bruges som en forløber for en de-duping-operation. Det kan vise os, hvad der vil blive slettet, hvis vi beslutter os for at slette dubletter. For at de-dupere tabellen er alt, hvad vi skal gøre, at erstatte den sidste SELECT * med DELETE .

Mulighed 6

Her er en mere kortfattet måde at få det samme output som det foregående eksempel:

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

Resultat:

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

Dette eksempel kræver ikke generering af vores eget separate rækkenummer.

Vi kan erstatte SELECT * med DELETE for at slette dubletterne.

Mulighed 7

Og endelig, her er en anden mulighed for at returnere dubletter:

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
);

Resultat:

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

  1. flere forespørgsler samme tabel, men i forskellige kolonner mysql

  2. Sådan fungerer RIGHT()-funktionen i SQL Server (T-SQL)

  3. 2 måder at returnere Unix-tidsstemplet i SQLite

  4. Konfigurer SQL-job i SQL Server ved hjælp af T-SQL