Poniższe zapytania mogą służyć do zwracania zduplikowanych wierszy w SQLite.
Tutaj zduplikowane wiersze zawierają zduplikowane wartości we wszystkich kolumnach, w tym w kolumnie ID.
Przykładowe dane
Załóżmy, że mamy tabelę z następującymi danymi:
SELECT * FROM Pets;
Wynik:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 1 Wag Dog 2 Scratch Cat 3 Tweet Bird 4 Bark Dog 4 Bark Dog 4 Bark Dog
Pierwsze dwa wiersze są duplikatami, podobnie jak ostatnie trzy wiersze. Dzieje się tak, ponieważ wszystkie trzy kolumny zawierają te same wartości w każdym zduplikowanym wierszu.
Opcja 1
Możemy użyć następującego zapytania, aby zobaczyć, ile wierszy jest duplikatami:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Wynik:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1 4 Bark Dog 3
Tutaj pogrupowaliśmy wiersze według wszystkich kolumn i zwróciliśmy liczbę wierszy każdej grupy. To mówi nam, czy wiersz jest unikalny (liczba 1), czy duplikat (liczba większa niż 1).
Możemy uporządkować to według liczby w porządku malejącym, tak aby wiersze z największą liczbą duplikatów pojawiły się jako pierwsze:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY Count(*) DESC;
Wynik:
PetId PetName PetType Count ----- ------- ------- ----- 4 Bark Dog 3 1 Wag Dog 2 2 Scratch Cat 1 3 Tweet Bird 1
Opcja 2
Jeśli chcemy wyświetlić tylko zduplikowane wiersze, możemy użyć HAVING
klauzula zwracająca tylko wiersze o liczbie większej niż 1:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY PetId;
Wynik:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 4 Bark Dog 3
Opcja 3
Inną opcją jest użycie ROW_NUMBER()
funkcja okna:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Wynik:
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
PARTITION BY
klauzula dzieli zbiór wyników utworzony przez FROM
klauzuli na przegrody, do których funkcja jest stosowana. Kiedy określamy partycje dla zestawu wyników, każda partycja powoduje, że numeracja zaczyna się od nowa (tj. numeracja rozpocznie się od 1 dla pierwszego wiersza w każdej partycji).
Opcja 4
Możemy użyć powyższego zapytania jako wspólnego wyrażenia tabelowego:
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;
Wynik:
PetId PetName PetType Row_Number ----- ------- ------- ---------- 1 Wag Dog 2 4 Bark Dog 2 4 Bark Dog 3
Zwraca to tylko nadmiarowe wiersze z pasujących duplikatów. Więc jeśli są dwa identyczne wiersze, zwraca jeden z nich. Jeśli są trzy identyczne wiersze, zwraca dwa i tak dalej.
To zapytanie może być przydatne do pokazania, ile wierszy zostanie usuniętych z tabeli podczas operacji usuwania duplikatów. W niektórych innych DBMS (przynajmniej w SQL Server) możemy zastąpić ostatni SELECT *
z DELETE
aby usunąć zduplikowane wiersze z tabeli. Ale SQLite nie pozwoli nam zaktualizować CTE w ten sposób.
Na szczęście następne dwie opcje można zmodyfikować, aby wykonać usunięcie.
Opcja 5
Możemy skorzystać z rowid
SQLite :
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
);
Wynik:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 4 Bark Dog 4 Bark Dog
Jak to działa? Domyślnie każdy wiersz w SQLite ma specjalną kolumnę, zwykle nazywaną rowid
, który jednoznacznie identyfikuje ten wiersz w tabeli. W razie potrzeby można to usunąć, ale o ile nie zostało to wyraźnie usunięte, będziesz mógł go wykorzystać w swoich zapytaniach.
Opcja 6
I na koniec, oto kolejna opcja, która wykorzystuje rowid
SQLite :
SELECT * FROM Pets
WHERE rowid > (
SELECT MIN(rowid) FROM Pets p2
WHERE Pets.PetName = p2.PetName
AND Pets.PetType = p2.PetType
);
Wynik:
PetId PetName PetType ----- ------- ------- 1 Wag Dog 4 Bark Dog 4 Bark Dog