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