SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

6 maneiras de excluir linhas duplicadas que têm uma chave primária no SQLite


Abaixo estão seis exemplos que excluem linhas duplicadas de uma tabela no SQLite quando essas linhas têm uma chave primária ou uma coluna de identificador exclusivo.

Nesses casos, a chave primária deve ser ignorada ao comparar duplicatas (devido ao fato de que as chaves primárias evitam linhas duplicadas por definição).

Dados de amostra


Nossos exemplos usam os seguintes dados:
SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 2 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 6 Wag Johnson 7 Wag Johnson  
Podemos ver que as duas primeiras linhas contêm duplicatas, assim como as três últimas linhas.

O DogId A coluna contém valores únicos (porque é a chave primária da tabela) e, portanto, estritamente falando, não há duplicatas. Mas em situações da vida real, muitas vezes você desejará desduplicar tabelas que contêm chaves primárias. Portanto, nos exemplos a seguir, ignoramos a chave primária e excluímos as linhas que contêm valores duplicados nas colunas restantes.

Opção 1


Aqui está nossa primeira opção para desduplicar a tabela acima:
DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 

A tabela foi desduplicada como esperado.

Alternativamente, podemos usar o MAX() função em vez de MIN() função para alterar quais linhas são excluídas. Farei isso no próximo exemplo.

Opção 2


Neste exemplo (e nos exemplos a seguir), vamos supor que a tabela foi restaurada ao seu estado original (com as duplicatas).

Aqui está outra consulta que exclui linhas duplicadas e seleciona as linhas restantes:
DELETE FROM Dogs WHERE DogId IN (
    SELECT d2.DogId 
    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
    )
);

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------2 Bark Smith 3 Woof Jones 4 Ruff Robinson7 Wag Johnson 

A tabela agora foi desduplicada.

Observe que usei o MAX() função em vez de MIN() que usei no exemplo anterior. Podemos ver o efeito que isso tem na operação de desduplicação. Ele excluiu diferentes linhas da tabela.

Opção 3


Aqui está uma opção que não requer o uso de MIN() ou MAX() :
DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
);

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 

Opção 4


Aqui está outra opção:
DELETE FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 

Opção 5


Por padrão, cada linha no SQLite tem uma coluna especial, geralmente chamada de rowid , que identifica exclusivamente essa linha na tabela. A menos que tenha sido explicitamente removido da tabela, você pode usá-lo como um identificador exclusivo para cada linha. Esse método pode ser útil se você não conseguir referenciar a chave primária por algum motivo (ou se a tabela não tiver uma chave primária).

Podemos, portanto, usar o rowid em nossa consulta em vez do DogId coluna:
DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
);

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson 

Opção 6


E aqui está o outro exemplo, mas com rowid em vez da chave primária:
DELETE FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs; 

Resultado:
DogId FirstName LastName----- --------- --------1 Bark Smith 3 Woof Jones 4 Ruff Robinson5 Wag Johnson