Oto siedem sposobów zwracania zduplikowanych wierszy w MariaDB, gdy te wiersze mają klucz podstawowy lub inną kolumnę unikatowego identyfikatora.
Dlatego zduplikowane wiersze mają dokładnie te same wartości we wszystkich kolumnach, z wyjątkiem kolumny z unikalnym identyfikatorem.
Przykładowe dane
W naszych przykładach użyjemy następujących danych:
SELECT * FROM Dogs;
Wynik:
+-------+-----------+----------+ | DogId | FirstName | LastName | +-------+-----------+----------+ | 1 | Bark | Smith | | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +-------+-----------+----------+
Pierwsze dwa wiersze są duplikatami (z wyjątkiem DogId
kolumna, która jest kluczem podstawowym tabeli i zawiera unikatową wartość we wszystkich wierszach). Ostatnie trzy wiersze również są duplikatami (z wyjątkiem DogId
kolumna).
Kolumna klucza podstawowego zapewnia, że nie ma zduplikowanych wierszy, co zwykle jest dobrą rzeczą w systemach RDBMS. Jednak z definicji oznacza to, że nie ma duplikatów. W naszym przypadku kolumna klucza podstawowego jest liczbą rosnącą, a jej wartość nie ma znaczenia i nie jest istotna. Dlatego musimy zignorować ten wiersz, jeśli chcemy znaleźć duplikaty w kolumnach, które są istotne.
Opcja 1
Możemy użyć GROUP BY
klauzula, aby pogrupować kolumny według ich znaczących kolumn, a następnie użyj COUNT()
funkcja zwracająca liczbę identycznych wierszy:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;
Wynik:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Ruff | Robinson | 1 | | Wag | Johnson | 3 | | Woof | Jones | 1 | +-----------+----------+-------+
Udało nam się wykluczyć kolumnę klucza podstawowego, pomijając ją w naszym zapytaniu.
Wynik mówi nam, że istnieją dwa wiersze zawierające Bark Smith i trzy wiersze zawierające Wag Johnson. Są to duplikaty (lub trzy egzemplarze w przypadku Wag Johnson). Pozostałe dwa wiersze nie mają żadnych duplikatów.
Opcja 2
Możemy wykluczyć nieduplikaty z danych wyjściowych za pomocą HAVING
klauzula:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;
Wynik:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Wag | Johnson | 3 | +-----------+----------+-------+
Opcja 3
Możliwe jest również sprawdzenie duplikatów w połączonych kolumnach. Na przykład możemy użyć CONCAT()
do łączenia naszych dwóch kolumn użyj funkcji DISTINCT
słowa kluczowego, aby uzyskać różne wartości, a następnie użyj COUNT()
funkcja zwracająca liczbę:
SELECT
DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);
Wynik:
+---------------+-------+ | DogName | Count | +---------------+-------+ | Bark Smith | 2 | | Ruff Robinson | 1 | | Wag Johnson | 3 | | Woof Jones | 1 | +---------------+-------+
Opcja 4
Możemy użyć ROW_NUMBER()
funkcja z PARTITION BY
klauzula:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs;
Wynik:
+-------+-----------+----------+------------+ | 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 | +-------+-----------+----------+------------+
Spowoduje to utworzenie nowej kolumny z numerem wiersza, który zwiększa się za każdym razem, gdy pojawia się duplikat, ale resetuje się ponownie, gdy pojawia się unikalny wiersz.
W tym przypadku nie grupujemy wyników, co oznacza, że możemy zobaczyć każdy zduplikowany wiersz, w tym jego kolumnę z unikalnym identyfikatorem.
Opcja 5
Możemy również użyć poprzedniego przykładu jako wspólnego wyrażenia tabelowego w większym zapytaniu:
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;
Wynik:
+-------+-----------+----------+------------+ | DogId | FirstName | LastName | Row_Number | +-------+-----------+----------+------------+ | 2 | Bark | Smith | 2 | | 5 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | +-------+-----------+----------+------------+
Wyklucza to nieduplikaty z danych wyjściowych i wyklucza jeden wiersz każdego duplikatu z danych wyjściowych.
To zapytanie może być używane jako prekursor operacji usuwania duplikatów. Może nam pokazać, co zostanie usunięte, jeśli zdecydujemy się usunąć duplikaty. Aby usunąć duplikat tabeli, wystarczy zastąpić ostatni SELECT *
z DELETE
.
Opcja 6
Oto bardziej zwięzły sposób na uzyskanie tego samego wyniku, co w poprzednim przykładzie:
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
Wynik:
+-------+-----------+----------+ | DogId | FirstName | LastName | +-------+-----------+----------+ | 2 | Bark | Smith | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +-------+-----------+----------+
Ten przykład nie wymaga generowania własnego oddzielnego numeru wiersza.
Możemy zastąpić SELECT *
z DELETE
aby usunąć duplikaty.
Opcja 7
I wreszcie, oto kolejna opcja zwracania duplikatów:
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
);
Wynik:
+-------+-----------+----------+-------+-----------+----------+ | DogId | FirstName | LastName | DogId | FirstName | LastName | +-------+-----------+----------+-------+-----------+----------+ | 2 | Bark | Smith | 1 | Bark | Smith | | 7 | Wag | Johnson | 5 | Wag | Johnson | | 7 | Wag | Johnson | 6 | Wag | Johnson | +-------+-----------+----------+-------+-----------+----------+