SQLite
 sql >> база данни >  >> RDS >> SQLite

11 начина за намиране на дублиращи се редове, докато игнорирате първичния ключ в SQLite

Ето единадесет опции за връщане на дублиращи се редове в SQLite, когато тези редове имат първичен ключ или някаква друга колона с уникален идентификатор (но искате да игнорирате първичния ключ).

Това означава, че дублираните редове споделят абсолютно едни и същи стойности във всички колони с изключение на техния първичен ключ/колоната с уникален идентификатор.

Примерни данни

Ще използваме следните данни за нашите примери:

SELECT * FROM Dogs; 

Резултат:

DogId Име Фамилия----- --------- --------1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 6 Wag Johnson 7 Wag Johnson  

Първите два реда са дублирани (с изключение на DogId колона, която е първичен ключ на таблицата и съдържа уникална стойност във всички редове). Последните три реда също са дублирани (с изключение на DogId колона).

Колоната с първичен ключ гарантира, че няма дублиращи се редове, което е добра практика в RDBMS, тъй като първичните ключове помагат за налагане на целостта на данните. Но тъй като първичните ключове предотвратяват дублиране на редове, те имат потенциала да попречат на способността ни да намираме дубликати.

В нашата таблица по-горе колоната с първичен ключ е нарастващо число и стойността й няма значение и не е значима. Следователно трябва да игнорираме този ред, ако искаме да намерим дубликати в другите колони.

Опция 1

Можем да изпълним заявка с GROUP BY клауза, за да групирате колоните по значимите им колони, след това използвайте COUNT() функция за връщане на броя на еднакви редове:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
ORDER BY Count DESC; 

Резултат:

Първо име Фамилия Брой--------- --------- -----Уаг Джонсън 3 Барк Смит 2 Ръф Робинсън 1 Уф Джоунс 1 

Тук изключихме колоната с първичен ключ, като я пропуснахме от нашата заявка. Подредихме го и по брой в низходящ ред, така че дубликатите да се показват първи.

Резултатът ни казва, че има три реда, съдържащи Уаг Джонсън и два реда, съдържащи Барк Смит. Това са дубликати (или три екземпляра в случая на Уаг Джонсън). Другите два реда нямат дубликати.

Опция 2

Можем да използваме HAVING клауза за изключване на недублирани от изхода:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1
ORDER BY Count DESC; 

Резултат:

Първо име Фамилия Брой--------- --------- -----Уаг Джонсън 3 Барк Смит 2 

Опция 3

Ето пример за проверка за дубликати на свързани колони. В този случай използваме DISTINCT ключова дума, за да получите различни стойности, след това използвайте COUNT() функция за връщане на броя:

SELECT
    DISTINCT FirstName || ' ' || LastName AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName || ' ' || LastName
ORDER BY Count DESC; 

Резултат:

Брой на имената на кучета------------ -----Ваг Джонсън 3 Барк Смит 2 Уф Джоунс 1 Ръф Робинсън 1 

Опция 4

По подразбиране всеки ред в SQLite има специална колона, обикновено наричана rowid , който уникално идентифицира този ред в таблицата. Освен ако не е премахнат изрично от таблицата, можете да го използвате като уникален идентификатор за всеки ред.

Следователно можем да използваме rowid в нашата заявка:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
); 

Резултат:

DogId Име Фамилия----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Бихме могли да заменим SELECT * с DELETE за извършване на операция за премахване на дупки на масата.

Имайте предвид, че можехме да използваме DogId колона (нашия първичен ключ) вместо rowid ако искахме. Това каза, rowid може да бъде полезно, ако по някаква причина не можете да използвате колоната с първичен ключ или ако таблицата няма първичен ключ.

Опция 5

Ето още една заявка, която използва rowid :

SELECT * FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Резултат:

DogId Име Фамилия----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Както в предишния пример, бихме могли да заменим SELECT * с DELETE за да изтриете дублиращите се редове.

Опция 6

Двата rowid опциите по-горе са страхотни, ако трябва напълно да игнорирате първичния ключ във вашата заявка (или ако изобщо нямате колона с първичен ключ). Въпреки това, както споменахме, все още има опция за замяна на rowid с колоната с първичен ключ – в нашия случай DogId колона:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
); 

Резултат:

DogId Име Фамилия----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Опция 7

А ето и другата заявка с rowid заменен от DogId колона:

SELECT * FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
); 

Резултат:

DogId Име Фамилия----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Опция 8

Друг начин да го направите е да използвате ROW_NUMBER() функция на прозореца:

SELECT 
    *,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS Row_Number
FROM Dogs; 

Резултат:

DogId Име на фамилия Ред_Номер----- --------- -------- ----------1 Bark Smith 1 2 Bark Smith 2 4 Ruff Robinson 1 5 Wag Johnson 1 6 Wag Johnson 2 7 Wag Johnson 3 3 Woof Jones 1 

Използване на PARTITION клауза води до добавяне на нова колона с номер на ред, който се увеличава всеки път, когато има дубликат, но се нулира отново, когато има уникален ред.

В този случай не групираме резултатите, което означава, че можем да видим всеки дублиран ред, включително колоната с уникален идентификатор.

Опция 9

Можем също да използваме предишния пример като общ табличен израз в по-голяма заявка:

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; 

Резултат:

DogId Име на фамилия Ред_Номер----- --------- -------- ----------2 Bark Smith 2 6 Wag Johnson 2 7 Wag Johnson 3 

Това изключва недубликатите от изхода и изключва един ред от всеки дубликат от изхода.

Опция 10

Ето още един начин да получите същия изход като предишния пример:

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    ); 

Резултат:

DogId Име Фамилия----- --------- --------2 Bark Smith 6 Wag Johnson 7 Wag Johnson 

Опция 11

Ето още една опция за избор на дубликати от нашата таблица:

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
); 

Резултат:

DogId FirstName Фамилия DogId FirstName Фамилия----- --------- -------- ----- --------- ----- ---2 Bark Smith 1 Bark Smith 7 Wag Johnson 5 Wag Johnson 7 Wag Johnson 6 Wag Johnson 

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Android Room Database, извличане на конкретна стойност на последния въведен запис

  2. Нямате заключване на базата данни! в android

  3. Добавете колона към съществуваща таблица в SQLite

  4. Използване на Robolectric с SQLiteAssetHelper

  5. Копиране на sqlite в активи на android studio не работи