sql >> データベース >  >> RDS >> Database

SQLテーブルから重複を削除する複数の方法

    概要

    この記事では、SQLテーブルから重複行を削除するために利用できる2つの異なるアプローチについて説明します。これは、時間どおりに行われないと、データが大きくなるにつれて時間の経過とともに困難になることがよくあります。

    重複する行の存在は、SQL開発者とテスターが時々直面する一般的な問題ですが、これらの重複する行は、この記事で説明するさまざまなカテゴリに分類されます。

    この記事では、データベーステーブルに挿入されたデータが重複レコードの導入につながる特定のシナリオに焦点を当て、次に重複を削除する方法を詳しく見て、最後にこれらの方法を使用して重複を削除します。

    サンプルデータの準備

    重複を削除するために利用できるさまざまなオプションの調査を開始する前に、この時点でサンプルデータベースを設定することをお勧めします。これは、重複データがシステムに侵入する状況と、それを根絶するために使用するアプローチを理解するのに役立ちます。 。

    サンプルデータベース(UniversityV2)のセットアップ

    学生のみで構成される非常に単純なデータベースを作成することから始めます。 最初の表。

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

    生徒のテーブルを作成する

    Studentテーブルに2つのレコードのみを追加しましょう:

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

    データチェック

    現在、2つの異なるレコードを含むテーブルを表示します。

    -- View Student table data
    SELECT [StudentId]
          ,[Name]
          ,[Course]
          ,[Marks]
          ,[ExamDate]
      FROM [UniversityV2].[dbo].[Student]
    

    1つのテーブルと2つの異なる(異なる)レコードを含むデータベースを設定することで、サンプルデータを正常に準備できました。

    ここでは、単純な状況から少し複雑な状況まで、重複が導入および削除される可能性のあるいくつかのシナリオについて説明します。

    ケース01:重複の追加と削除

    次に、Studentテーブルに重複する行を導入します。

    前提条件

    この場合、学生の名前の場合、テーブルには重複したレコードがあると言われます 、コースマーク 、および ExamDate 学生のIDであっても、複数のレコードで一致する 違います。

    したがって、2人の学生が同じ名前、コース、マーク、および試験日を持つことはできないと想定しています。

    StudentAsifの重複データの追加

    Student:Asifの重複レコードを意図的に挿入しましょう 学生に 次のような表:

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

    重複する学生データを表示する

    学生を表示する 重複レコードを表示するテーブル:

    -- View Student table data
    SELECT [StudentId]
          ,[Name]
          ,[Course]
          ,[Marks]
          ,[ExamDate]
      FROM [UniversityV2].[dbo].[Student]
    

    自己参照方法による重複の検索

    このテーブルに何千ものレコードがある場合、テーブルを表示してもあまり役に立ちません。

    自己参照方式では、同じテーブルへの2つの参照を取得し、他のIDよりも小さくまたは大きくなるIDを除いて、列ごとのマッピングを使用してそれらを結合します。

    自己参照メソッドを見て、次のような重複を見つけましょう。

    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
    

    上記のスクリプトの出力には、重複するレコードのみが表示されます。

    自己参照方法-2による重複の検索

    自己参照を使用して重複を見つける別の方法は、次のようにINNERJOINを使用することです。

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

    自己参照方式による重複の削除

    次の構文に沿ってDELETEを使用することを除いて、重複を見つけるために使用したのと同じ方法を使用して重複を削除できます。

    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
    

    重複削除後のデータチェック

    重複を削除した後、レコードをすばやく確認しましょう:

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

    重複ビューの作成と削除重複ストアドプロシージャ

    スクリプトがSQLで重複する行を正常に検出して削除できることがわかったので、使いやすさのためにそれらをビューとストアドプロシージャに変換することをお勧めします。

    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
    

    複数の重複レコードの追加と表示

    ここで、学生にさらに4つのレコードを追加しましょう。 テーブルとすべてのレコードは、同じ名前、コース、マーク、試験日を持つように重複しています:

    --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]
    
    

    UspRemoveDuplicatesプロシージャを使用した重複の削除

    USE UniversityV2
    
    -- Removing multiple duplicates
    EXEC UspRemoveDuplicates
    

    複数の重複を削除した後のデータチェック

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

    ケース02:同じIDの重複の追加と削除

    これまでに、異なるIDを持つ重複レコードを特定しましたが、IDが同じである場合はどうなりますか。

    たとえば、主キーのないテキストファイルまたはExcelファイルからテーブルが最近インポートされたシナリオを考えてみてください。

    前提条件

    この場合、一部のID列を含むすべての列の値が完全に同じであり、主キーが欠落しているために重複レコードを入力しやすくなっている場合、テーブルには重複レコードがあると言われます。

    主キーなしでコーステーブルを作成する

    主キーがない場合に重複するレコードがテーブルに分類されるシナリオを再現するために、最初に新しいコースを作成しましょう。 次のように、University2データベースに主キーがないテーブル

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

    人口コーステーブル

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

    データチェック

    コースを表示する テーブル:

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

    コーステーブルに重複データを追加する

    次に、重複をコースに挿入します テーブル:

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

    重複するコースデータを表示する

    表を表示するには、すべての列を選択してください:

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

    集計方法による重複の検索

    集計カウント(*)関数を使用してすべての行をカウントするとともに、すべての列を選択した後、すべての列を合計1つ以上でグループ化することにより、集計メソッドを使用して正確な重複を見つけることができます。

    -- Finding duplicates using Aggregate method
    SELECT <column1>,<column2>,<column3>…
      ,COUNT(*) AS Total_Records
    FROM <Table>
    GROUP BY <column1>,<column2>,<column3>…
    HAVING COUNT(*)>1
    

    これは次のように適用できます:

    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
    

    集計方法による重複の削除

    次のように集計メソッドを使用して重複を削除しましょう:

    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
    

    データチェック

    UniversityV2を使用

    そのため、2つの異なるシナリオに基づく2つの異なる方法を使用して、データベーステーブルから重複を削除する方法を正常に学習しました。

    やるべきこと

    データベーステーブルを簡単に識別して、重複する値から解放できるようになりました。

    1. UspRemoveDuplicatesByAggregateを作成してみます 上記の方法に基づいてストアドプロシージャを作成し、ストアドプロシージャを呼び出して重複を削除します

    2.上記で作成したストアドプロシージャ(UspRemoveDuplicatesByAggregates)を変更して、この記事に記載されているクリーンアップのヒントを実装してみてください。

      DROP TABLE CourseNew
    -- (5) You can drop the Course_OLD table afterwards
    -- (6) You can remove Duplicate_Records column from Course table afterwards
    

    3. UspRemoveDuplicatesByAggregate を確認できますか? 重複を削除した後でも、ストアドプロシージャを可能な限り何度でも実行して、プロシージャが最初から一貫していることを示すことができますか?

    4.以前の記事「テスト駆動データベース開発(TDDD)の開始にジャンプ–パート1」を参照して、SQLDevBlogデータベーステーブルに重複を挿入してみてください。その後、このヒントに記載されている両方の方法を使用して重複を削除してみてください。

    5.別のサンプルデータベースEmployeesSampleを作成してみてください 以前の記事「データベース単体テストで依存関係とデータを分離する方法」を参照し、重複をテーブルに挿入して、このヒントから学んだ両方の方法を使用してそれらを削除してみてください。

    便利なツール:

    dbForge Data Compare for SQL Server –ビッグデータを処理できる強力なSQL比較ツール。


    1. java.sql.SQLExceptionの取得:ResultSetを閉じた後の操作は許可されていません

    2. 通常よりもきめ細かく報告– Microsoft Access

    3. リレーショナルオブジェクトの主キーを処理するAndroidレルム

    4. トラブルシューティング:リダイレクトが多すぎます