Database
 sql >> Base de Dados >  >> RDS >> Database

Várias maneiras de excluir duplicatas de tabelas SQL

Visão geral


Este artigo discute duas abordagens diferentes disponíveis para remover linhas duplicadas de tabelas SQL, o que geralmente se torna difícil com o tempo à medida que os dados aumentam se isso não for feito a tempo.

A presença de linhas duplicadas é um problema comum que os desenvolvedores e testadores de SQL enfrentam de tempos em tempos, no entanto, essas linhas duplicadas se enquadram em várias categorias diferentes que discutiremos neste artigo.

Este artigo se concentra em um cenário específico, quando os dados inseridos em uma tabela de banco de dados levam à introdução de registros duplicados e, em seguida, examinaremos mais detalhadamente os métodos para remover duplicatas e, finalmente, remover as duplicatas usando esses métodos.

Preparando dados de amostra


Antes de começarmos a explorar as diferentes opções disponíveis para remover duplicatas, vale a pena neste momento configurar um banco de dados de exemplo que nos ajudará a entender as situações em que dados duplicados chegam ao sistema e as abordagens a serem usadas para erradicá-los .

Configurar banco de dados de amostra (UniversityV2)


Comece criando um banco de dados muito simples que consiste apenas em um Aluno mesa no início.
-- (1) Create UniversityV2 sample database
CREATE DATABASE UniversityV2;
GO

USE UniversityV2

CREATE TABLE [dbo].[Student] (
    [StudentId] INT           IDENTITY (1, 1) NOT NULL,
    [Name]      VARCHAR (30)  NULL,
    [Course]    VARCHAR (30)  NULL,
    [Marks]     INT           NULL,
    [ExamDate]  DATETIME2 (7) NULL,
    CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED ([StudentId] ASC)
);

Preencher a Tabela do Aluno


Vamos adicionar apenas dois registros à tabela Aluno:
-- Adding two records to the Student table
SET IDENTITY_INSERT [dbo].[Student] ON
INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (1, N'Asif', N'Database Management System', 80, N'2016-01-01 00:00:00')
INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (2, N'Peter', N'Database Management System', 85, N'2016-01-01 00:00:00')
SET IDENTITY_INSERT [dbo].[Student] OFF

Verificação de dados


Veja a tabela que contém dois registros distintos no momento:
-- View Student table data
SELECT [StudentId]
      ,[Name]
      ,[Course]
      ,[Marks]
      ,[ExamDate]
  FROM [UniversityV2].[dbo].[Student]

Você preparou com êxito os dados de amostra configurando um banco de dados com uma tabela e dois registros distintos (diferentes).

Vamos discutir agora alguns cenários potenciais em que duplicatas foram introduzidas e excluídas a partir de situações simples a ligeiramente complexas.

Caso 01:Adicionando e removendo duplicatas


Agora vamos introduzir linha(s) duplicada(s) na tabela Aluno.

Pré-condições


Nesse caso, diz-se que uma tabela tem registros duplicados se o Nome de um aluno , Curso , Marcas e Data do Exame coincidem em mais de um registro, mesmo que o ID do aluno é diferente.

Assim, assumimos que dois alunos não podem ter o mesmo nome, curso, notas e data de exame.

Adicionando dados duplicados para Aluno Asif


Vamos inserir deliberadamente um registro duplicado para Aluno:Asif para o Aluno tabela da seguinte forma:
-- Adding Student Asif duplicate record to the Student table
SET IDENTITY_INSERT [dbo].[Student] ON
INSERT INTO [dbo].[Student] ([StudentId], [Name], [Course], [Marks], [ExamDate]) VALUES (3, N'Asif', N'Database Management System', 80, N'2016-01-01 00:00:00')
SET IDENTITY_INSERT [dbo].[Student] OFF	

Visualizar dados duplicados do aluno


Veja o Aluno tabela para ver registros duplicados:
-- View Student table data
SELECT [StudentId]
      ,[Name]
      ,[Course]
      ,[Marks]
      ,[ExamDate]
  FROM [UniversityV2].[dbo].[Student]

Encontrando duplicatas pelo método de auto-referência


E se houver milhares de registros nesta tabela, a visualização da tabela não ajudará muito.

No método de auto-referência, pegamos duas referências à mesma tabela e as juntamos usando o mapeamento coluna por coluna, com exceção do ID que é menor ou maior que o outro.

Vejamos o método de auto-referência para encontrar duplicatas que se parecem com isso:
USE UniversityV2

-- Self-Referencing method to finding duplicate students having same name, course, marks, exam date
SELECT S1.[StudentId] as S1_StudentId,S2.StudentId as S2_StudentID
	,S1.Name AS S1_Name, S2.Name as S2_Name
	,S1.Course AS S1_Course, S2.Course as S2_Course
	,S1.ExamDate as S1_ExamDate, S2.ExamDate AS S2_ExamDate
  FROM [dbo].[Student] S1,[dbo].[Student] S2
  WHERE S1.StudentId<S2.StudentId AND
  S1.Name=S2.Name
  AND 
  S1.Course=S2.Course
  AND
  S1.Marks=S2.Marks
  AND
  S1.ExamDate=S2.ExamDate

A saída do script acima nos mostra apenas os registros duplicados:

Encontrando duplicatas pelo método de auto-referência-2


Outra maneira de encontrar duplicatas usando auto-referência é usar INNER JOIN da seguinte forma:
-- Self-Referencing method 2 to find duplicate students having same name, course, marks, exam date
SELECT S1.[StudentId] as S1_StudentId,S2.StudentId as S2_StudentID
	,S1.Name AS S1_Name, S2.Name as S2_Name
	,S1.Course AS S1_Course, S2.Course as S2_Course
	,S1.ExamDate as S1_ExamDate, S2.ExamDate AS S2_ExamDate
  FROM [dbo].[Student] S1
  INNER JOIN
  [dbo].[Student] S2
  
  ON S1.Name=S2.Name
  AND 
  S1.Course=S2.Course
  AND
  S1.Marks=S2.Marks
  AND
  S1.ExamDate=S2.ExamDate
  WHERE S1.StudentId<S2.StudentId

Remoção de duplicatas pelo método de auto-referência


Podemos remover as duplicatas usando o mesmo método que usamos para encontrar duplicatas, com exceção de usar DELETE de acordo com sua sintaxe da seguinte maneira:
USE UniversityV2

-- Removing duplicates by using Self-Referencing method
DELETE S2
  FROM [dbo].[Student] S1,
  [dbo].[Student] S2
WHERE S1.StudentId < S2.StudentId
  AND S1.Name = S2.Name
  AND S1.Course = S2.Course
  AND S1.Marks = S2.Marks
  AND S1.ExamDate = S2.ExamDate

Verificação de dados após a remoção de duplicatas


Vamos verificar rapidamente os registros depois de removermos as duplicatas:
USE UniversityV2

-- View Student data after duplicates have been removed
SELECT
  [StudentId]
 ,[Name]
 ,[Course]
 ,[Marks]
 ,[ExamDate]
FROM [UniversityV2].[dbo].[Student]

Criando a visualização de duplicatas e removendo o procedimento armazenado de duplicatas


Agora que sabemos que nossos scripts podem encontrar e excluir com sucesso linhas duplicadas no SQL, é melhor transformá-las em visualização e procedimento armazenado para facilitar o uso:
USE UniversityV2;
GO

-- Creating view find duplicate students having same name, course, marks, exam date using Self-Referencing method
CREATE VIEW dbo.Duplicates

AS

SELECT
  S1.[StudentId] AS S1_StudentId
 ,S2.StudentId AS S2_StudentID
 ,S1.Name AS S1_Name
 ,S2.Name AS S2_Name
 ,S1.Course AS S1_Course
 ,S2.Course AS S2_Course
 ,S1.ExamDate AS S1_ExamDate
 ,S2.ExamDate AS S2_ExamDate
FROM [dbo].[Student] S1
    ,[dbo].[Student] S2
WHERE S1.StudentId < S2.StudentId
AND S1.Name = S2.Name
AND S1.Course = S2.Course
AND S1.Marks = S2.Marks
AND S1.ExamDate = S2.ExamDate

GO

-- Creating stored procedure to removing duplicates by using Self-Referencing method
CREATE PROCEDURE UspRemoveDuplicates
AS
BEGIN
  DELETE S2
    FROM [dbo].[Student] S1,
    [dbo].[Student] S2
  WHERE S1.StudentId < S2.StudentId
    AND S1.Name = S2.Name
    AND S1.Course = S2.Course
    AND S1.Marks = S2.Marks
    AND S1.ExamDate = S2.ExamDate
END

Adicionar e visualizar vários registros duplicados


Vamos agora adicionar mais quatro registros ao Aluno tabela e todos os registros são duplicados de forma que tenham o mesmo nome, curso, notas e data do exame:
--Adding multiple duplicates to Student table
INSERT INTO Student (Name,
Course,
Marks,
ExamDate)
  VALUES ('Peter', 'Database Management System', 85, '2016-01-01'),
  ('Peter', 'Database Management System', 85, '2016-01-01'),
  ('Peter', 'Database Management System', 85, '2016-01-01'),
  ('Peter', 'Database Management System', 85, '2016-01-01');

-- Viewing Student table after multiple records have been added to Student table
SELECT
  [StudentId]
 ,[Name]
 ,[Course]
 ,[Marks]
 ,[ExamDate]
FROM [UniversityV2].[dbo].[Student]

Remoção de duplicatas usando o procedimento UspRemoveDuplicates

USE UniversityV2

-- Removing multiple duplicates
EXEC UspRemoveDuplicates

Verificação de dados após a remoção de várias duplicatas

USE UniversityV2

--View Student table after multiple duplicates removal
SELECT
  [StudentId]
 ,[Name]
 ,[Course]
 ,[Marks]
 ,[ExamDate]
FROM [UniversityV2].[dbo].[Student]

Caso 02:Adicionando e removendo duplicatas com os mesmos IDs


Até agora, identificamos registros duplicados com IDs distintos, mas e se os IDs forem os mesmos.

Por exemplo, pense no cenário em que uma tabela foi importada recentemente de um arquivo de texto ou Excel que não possui chave primária.

Pré-condições


Nesse caso, diz-se que uma tabela tem registros duplicados se todos os valores da coluna forem exatamente os mesmos, incluindo alguma coluna de ID e a chave primária estiver ausente, o que facilitou a inserção dos registros duplicados.

Criar Tabela de Curso sem Chave Primária


Para reproduzir o cenário em que registros duplicados na ausência de uma chave primária caem em uma tabela, vamos primeiro criar um novo Curso tabela sem nenhuma chave primária no banco de dados University2 da seguinte forma:
USE UniversityV2

-- Creating Course table without primary key
CREATE TABLE [dbo].[Course] (
    [CourseId] INT           NOT NULL,
    [Name]     VARCHAR (30)  NOT NULL,
    [Detail]   VARCHAR (200) NULL,   
);

Preencher Tabela de Curso

-- Populating Course table
INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (1, N'T-SQL Programming', N'About T-SQL Programming')
INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (2, N'Tabular Data Modeling', N'This is about Tabular Data Modeling')
INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail]) VALUES (3, N'Analysis Services Fundamentals', N'This is about Analysis Services Fundamentals')

Verificação de dados


Veja o Curso tabela:
USE UniversityV2

-- Viewing Course table
SELECT CourseId
      ,Name
      ,Detail FROM dbo.Course

Adicionando dados duplicados na tabela do curso


Agora insira duplicatas no Curso tabela:
USE UniversityV2

-- Inserting duplicate records in Course table
INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail])
  VALUES (1, N'T-SQL Programming', N'About T-SQL Programming')
INSERT INTO [dbo].[Course] ([CourseId], [Name], [Detail])
  VALUES (1, N'T-SQL Programming', N'About T-SQL Programming')

Visualizar dados duplicados do curso


Selecione todas as colunas para visualizar a tabela:
USE UniversityV2

-- Viewing duplicate data in Course table
SELECT CourseId
      ,Name
      ,Detail FROM dbo.Course

Encontrando duplicatas pelo método agregado


Podemos encontrar duplicatas exatas usando o método agregado agrupando todas as colunas com um total de mais de uma depois de selecionar todas as colunas junto com a contagem de todas as linhas usando a função de contagem agregada(*):
-- Finding duplicates using Aggregate method
SELECT <column1>,<column2>,<column3>…
  ,COUNT(*) AS Total_Records
FROM <Table>
GROUP BY <column1>,<column2>,<column3>…
HAVING COUNT(*)>1

Isso pode ser aplicado da seguinte forma:
USE UniversityV2

-- Finding duplicates using Aggregate method
SELECT
  c.CourseId
 ,c.Name
 ,c.Detail
 ,COUNT(*) AS Duplicate_Records
FROM dbo.Course c
GROUP BY c.CourseId
        ,c.Name
        ,c.Detail
HAVING COUNT(*) > 1

Remoção de duplicatas por método agregado


Vamos remover as duplicatas usando o Método Agregado da seguinte forma:
USE UniversityV2

-- Removing duplicates using Aggregate method

-- (1) Finding duplicates and put them into a new table (CourseNew) as a single row
SELECT
  c.CourseId
 ,c.Name
 ,c.Detail
 ,COUNT(*) AS Duplicate_Records INTO CourseNew
FROM dbo.Course c

GROUP BY c.CourseId
        ,c.Name
        ,c.Detail
HAVING COUNT(*) > 1

-- (2) Rename Course (which contains duplicates) as Course_OLD 
EXEC sys.sp_rename @objname = N'Course'
                  ,@newname = N'Course_OLD'


-- (3) Rename CourseNew (which contains no duplicates) as Course 
EXEC sys.sp_rename @objname = N'CourseNew'
                  ,@newname = N'Course'

-- (4) Insert original distinct records into Course table from Course_OLD table
INSERT INTO Course (CourseId, Name, Detail)
  SELECT
    co.CourseId
   ,co.Name
   ,co.Detail
  FROM Course_OLD co
  WHERE co.CourseId <> (SELECT
      c.CourseId
    FROM Course c)
  ORDER BY CO.CourseId

-- (4) Data check
SELECT
  cn.CourseId
 ,cn.Name
 ,cn.Detail
FROM Course cn
                                      
-- Clean up 
-- (5) You can drop the Course_OLD table afterwards
-- (6) You can remove Duplicate_Records column from Course table afterwards

Verificação de dados


USE UniversityV2

Assim, aprendemos com sucesso como remover duplicatas de uma tabela de banco de dados usando dois métodos diferentes com base em dois cenários diferentes.

Coisas para fazer


Agora você pode identificar e liberar facilmente uma tabela de banco de dados do valor duplicado.

1. Tente criar o UspRemoveDuplicatesByAggregate procedimento armazenado com base no método mencionado acima e remova duplicatas chamando o procedimento armazenado

2. Tente modificar o procedimento armazenado criado acima (UspRemoveDuplicatesByAggregates) e implemente as dicas de limpeza mencionadas neste artigo.
  DROP TABLE CourseNew
-- (5) You can drop the Course_OLD table afterwards
-- (6) You can remove Duplicate_Records column from Course table afterwards

3. Você pode ter certeza de que o UspRemoveDuplicatesByAggregate procedimento armazenado pode ser executado tantas vezes quanto possível, mesmo após a remoção das duplicatas, para mostrar que o procedimento permanece consistente em primeiro lugar?

4. Consulte meu artigo anterior Jump to Start Test-Driven Database Development (TDDD) – Parte 1 e tente inserir duplicatas nas tabelas de banco de dados SQLDevBlog, depois tente remover as duplicatas usando os dois métodos mencionados nesta dica.

5. Tente criar outro banco de dados de amostra EmployeesSample referindo-se ao meu artigo anterior Art of Isolating Dependency and Data in Database Unit Testing e insira duplicatas nas tabelas e tente removê-las usando os dois métodos que você aprendeu com esta dica.

Ferramenta útil:


dbForge Data Compare for SQL Server – poderosa ferramenta de comparação SQL capaz de trabalhar com big data.