De volgende query's kunnen worden gebruikt om dubbele rijen in SQLite te retourneren.
Hier bevatten de dubbele rijen dubbele waarden in alle kolommen, inclusief de ID-kolom.
Voorbeeldgegevens
Stel dat we een tabel hebben met de volgende gegevens:
SELECT * FROM Pets;
Resultaat:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 1 Wag Dog 2 Scratch Cat 3 Tweet Bird 4 Bark Dog 4 Bark Dog 4 Bark Dog
De eerste twee rijen zijn duplicaten, evenals de laatste drie rijen. Dat komt omdat alle drie de kolommen dezelfde waarden bevatten in elke dubbele rij.
Optie 1
We kunnen de volgende query gebruiken om te zien hoeveel rijen duplicaten zijn:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Resultaat:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
Hier hebben we de rijen gegroepeerd op alle kolommen en het aantal rijen van elke groep geretourneerd. Dit vertelt ons of een rij uniek is (met een telling van 1) of een duplicaat (met een telling groter dan 1).
We kunnen het sorteren op telling in aflopende volgorde, zodat de rijen met de meeste duplicaten eerst verschijnen:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Resultaat:
PetId PetName PetType Count ----- ------- ------- ----- 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Optie 2
Als we alleen de dubbele rijen willen hebben, kunnen we de HAVING
. gebruiken clausule om alleen rijen te retourneren met een telling groter dan 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY PetId;
Resultaat:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 4 Bark Dog 3
Optie 3
Een andere optie is om de ROW_NUMBER()
. te gebruiken vensterfunctie:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Resultaat:
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
De PARTITION BY
clausule verdeelt de resultaatset geproduceerd door de FROM
clausule in partities waarop de functie wordt toegepast. Wanneer we partities specificeren voor de resultatenset, zorgt elke partitie ervoor dat de nummering opnieuw begint (d.w.z. de nummering begint bij 1 voor de eerste rij in elke partitie).
Optie 4
We kunnen de bovenstaande query gebruiken als een algemene tabeluitdrukking:
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;
Resultaat:
PetId PetName PetType Row_Number ----- ------- ------- ---------- 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Dit retourneert alleen de overtollige rijen van de overeenkomende duplicaten. Dus als er twee identieke rijen zijn, wordt er één geretourneerd. Als er drie identieke rijen zijn, worden er twee geretourneerd, enzovoort.
Deze query kan handig zijn om te laten zien hoeveel rijen er uit de tabel worden verwijderd bij een ontdubbelingsbewerking. In sommige andere DBMS'en (tenminste in SQL Server), kunnen we de laatste SELECT *
. vervangen met DELETE
om de dubbele rijen uit de tabel te verwijderen. Maar SQLite laat ons de CTE niet zo updaten.
Gelukkig kunnen de volgende twee opties worden gewijzigd om een verwijdering uit te voeren.
Optie 5
We kunnen profiteren van SQLite's rowid
:
SELECT * FROM Pets
WHERE EXISTS (
SELECT 1 FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
AND Pets.rowid > p2.rowid
);
Resultaat:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 4 Bark Dog 4 Bark Dog
Hoe werkt dit? Standaard heeft elke rij in SQLite een speciale kolom, meestal de rowid
, die die rij in de tabel op unieke wijze identificeert. Dit kan indien nodig worden verwijderd, maar tenzij het expliciet is verwijderd, kunt u het gebruiken in uw zoekopdrachten.
Optie 6
En tot slot, hier is nog een optie die gebruikmaakt van SQLite's rowid
:
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Resultaat:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 4 Bark Dog 4 Bark Dog