sql >> Databasteknik >  >> RDS >> MariaDB

7 sätt att returnera dubbletter av rader som har en primärnyckel i MariaDB

Här är sju sätt att returnera dubbletter av rader i MariaDB när dessa rader har en primärnyckel eller annan unik identifierarkolumn.

Därför delar dubblettraderna exakt samma värden i alla kolumner förutom deras unika identifierarkolumn.

Exempeldata

Vi använder följande data för våra exempel:

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 två första raderna är dubbletter (förutom DogId kolumn, som är tabellens primärnyckel och innehåller ett unikt värde över alla rader). De sista tre raderna är också dubbletter (förutom DogId kolumn).

Den primära nyckelkolumnen säkerställer att det inte finns några dubbletter av rader, vilket normalt är bra i RDBMS. Men per definition innebär detta att det inte finns några dubbletter. I vårt fall är primärnyckelkolumnen ett ökande tal, och dess värde har ingen betydelse och är inte signifikant. Vi måste därför ignorera den raden om vi vill hitta dubbletter i kolumnerna som är signifikant.

Alternativ 1

Vi kan använda GROUP BY sats för att gruppera kolumnerna efter deras signifikanta kolumner, använd sedan den COUNT() funktion för att returnera antalet identiska rader:

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 kunde utesluta primärnyckelkolumnen genom att utelämna den från vår fråga.

Resultatet berättar att det finns två rader som innehåller Bark Smith och tre rader som innehåller Wag Johnson. Dessa är dubbletter (eller triplikat i fallet med Wag Johnson). De andra två raderna har inga dubbletter.

Alternativ 2

Vi kan utesluta icke-duplikat från utdata 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 |
+-----------+----------+-------+

Alternativ 3

Det är också möjligt att söka efter dubbletter på sammanlänkade kolumner. Till exempel kan vi använda CONCAT() funktion för att sammanfoga våra två kolumner, använd DISTINCT nyckelord för att få distinkta värden, använd sedan COUNT() funktion för att returnera antalet:

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

Alternativ 4

Vi kan använda 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 |
+-------+-----------+----------+------------+

Detta skapar en ny kolumn med ett radnummer som ökar varje gång det finns en dubblett, men återställs igen när det finns en unik rad.

I det här fallet grupperar vi inte resultaten, vilket innebär att vi kan se varje dubblettrad, inklusive dess unika identifierarkolumn.

Alternativ 5

Vi kan också använda föregående exempel som ett vanligt tabelluttryck i en större fråga:

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

Detta utesluter icke-dubbletter från utgången, och det utesluter en rad av varje dubblett från utgången.

Denna fråga skulle kunna användas som en föregångare till en de-dupingoperation. Det kan visa oss vad som kommer att raderas om vi bestämmer oss för att ta bort dubbletter. För att de-dupera tabellen behöver vi bara ersätta den sista SELECT * med DELETE .

Alternativ 6

Här är ett mer kortfattat sätt att få samma utdata som föregående exempel:

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

Det här exemplet kräver inte att vi genererar vårt eget separata radnummer.

Vi kan ersätta SELECT * med DELETE för att ta bort dubbletterna.

Alternativ 7

Och slutligen, här är ett annat alternativ för att returnera dubbletter:

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. Oracle DB:Hur kan jag skriva fråga som ignorerar skiftläge?

  2. Hur kan flera rader sammanfogas till en i Oracle utan att skapa en lagrad procedur?

  3. Var kan man ändra värdet på small_case_table_names=2 i Windows xampp

  4. Vad i helvete är en DTU?