Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

7 Cara Menemukan Baris Duplikat saat Mengabaikan Kunci Utama di MySQL

Berikut adalah tujuh cara untuk mengembalikan baris duplikat di MySQL ketika baris tersebut memiliki kunci utama atau kolom pengenal unik lainnya.

Contoh Data

Kami akan menggunakan data berikut untuk contoh kami:

DROP TABLE IF EXISTS Dogs;
CREATE TABLE Dogs (
    DogId int PRIMARY KEY NOT NULL,
    FirstName varchar(50),
    LastName varchar(50)
    );

INSERT INTO Dogs VALUES
    (1, 'Bark', 'Smith'),
    (2, 'Bark', 'Smith'),
    (3, 'Woof', 'Jones'),
    (4, 'Ruff', 'Robinson'),
    (5, 'Wag', 'Johnson'),
    (6, 'Wag', 'Johnson'),
    (7, 'Wag', 'Johnson');
SELECT * FROM Dogs;

Hasil:

+-------+-----------+----------+
| DogId | FirstName | LastName |
+-------+-----------+----------+
|     1 | Bark      | Smith    |
|     2 | Bark      | Smith    |
|     3 | Woof      | Jones    |
|     4 | Ruff      | Robinson |
|     5 | Wag       | Johnson  |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Baris duplikat memiliki nilai yang sama persis di semua kolom kecuali untuk kunci utama/kolom ID uniknya.

Dua baris pertama adalah duplikat (kecuali untuk DogId kolom, yang merupakan kunci utama tabel, dan berisi nilai unik di semua baris). Tiga baris terakhir juga merupakan duplikat (kecuali untuk DogId kolom).

Kolom kunci utama memastikan bahwa tidak ada baris duplikat, yang biasanya merupakan hal yang baik di RDBMS. Namun, menurut definisi ini berarti tidak ada duplikat. Dalam kasus kami, kolom kunci utama adalah angka yang bertambah, dan nilainya tidak memiliki arti dan tidak signifikan. Oleh karena itu, kita perlu mengabaikan baris tersebut jika ingin menemukan duplikat di kolom yang adalah penting.

Opsi 1

Opsi pertama kami adalah menggunakan GROUP BY klausa untuk mengelompokkan kolom menurut kolom signifikannya, lalu gunakan COUNT() fungsi untuk mengembalikan jumlah baris identik:

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

Hasil:

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Woof      | Jones    |     1 |
| Ruff      | Robinson |     1 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Kami dapat mengabaikan kolom kunci utama dengan menghilangkannya dari kueri kami.

Hasilnya memberi tahu kita bahwa ada dua baris berisi Bark Smith dan tiga baris berisi Wag Johnson. Ini adalah duplikat (atau rangkap tiga dalam kasus Wag Johnson). Dua baris lainnya tidak memiliki duplikat.

Opsi 2

Kami dapat mengecualikan non-duplikat dari output dengan HAVING klausa:

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

Hasil:

+-----------+----------+-------+
| FirstName | LastName | Count |
+-----------+----------+-------+
| Bark      | Smith    |     2 |
| Wag       | Johnson  |     3 |
+-----------+----------+-------+

Opsi 3

Kami juga dapat memeriksa duplikat pada kolom gabungan. Misalnya, kita dapat menggunakan CONCAT() fungsi untuk menggabungkan dua kolom kami, gunakan DISTINCT kata kunci untuk mendapatkan nilai yang berbeda, lalu gunakan COUNT() berfungsi untuk mengembalikan hitungan:

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

Hasil:

+---------------+-------+
| DogName       | Count |
+---------------+-------+
| Bark Smith    |     2 |
| Woof Jones    |     1 |
| Ruff Robinson |     1 |
| Wag Johnson   |     3 |
+---------------+-------+

Opsi 4

Sebagai alternatif, kita dapat menggunakan ROW_NUMBER() fungsi dengan PARTITION BY klausa:

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

Hasil:

+-------+-----------+----------+----+
| DogId | FirstName | LastName | rn |
+-------+-----------+----------+----+
|     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 |
+-------+-----------+----------+----+

Ini membuat kolom baru dengan nomor baris yang bertambah setiap kali ada duplikat, tetapi disetel ulang lagi saat ada baris unik

Teknik ini memberikan kemungkinan manfaat karena kita tidak perlu mengelompokkan hasilnya. Ini berarti kita dapat melihat setiap baris duplikat, termasuk kolom pengenal uniknya.

Opsi 5

Kita dapat menggunakan contoh sebelumnya sebagai ekspresi tabel umum dalam kueri yang lebih besar:

WITH cte AS 
    (
        SELECT 
            *,
            ROW_NUMBER() OVER ( 
                PARTITION BY FirstName, LastName 
                ORDER BY FirstName, LastName
                ) AS rn
        FROM Dogs
    )
SELECT * FROM cte WHERE rn <> 1;

Hasil:

+-------+-----------+----------+----+
| DogId | FirstName | LastName | rn |
+-------+-----------+----------+----+
|     2 | Bark      | Smith    |  2 |
|     6 | Wag       | Johnson  |  2 |
|     7 | Wag       | Johnson  |  3 |
+-------+-----------+----------+----+

Teknik ini mengecualikan non-duplikat dari output, dan mengecualikan satu baris dari setiap duplikat dari output.

Kueri ini dapat digunakan sebagai pendahulu untuk operasi de-duping. Itu dapat menunjukkan kepada kita apa yang akan dihapus jika kita memutuskan untuk menghapus duplikat. Untuk menghilangkan penipuan tabel, yang perlu kita lakukan hanyalah mengganti SELECT * . yang terakhir dengan DELETE .

Opsi 6

Berikut cara yang lebih ringkas untuk mendapatkan hasil yang sama seperti contoh sebelumnya:

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

Hasil:

+-------+-----------+----------+
| DogId | FirstName | LastName |
+-------+-----------+----------+
|     2 | Bark      | Smith    |
|     6 | Wag       | Johnson  |
|     7 | Wag       | Johnson  |
+-------+-----------+----------+

Teknik ini tidak mengharuskan kita untuk membuat nomor baris terpisah dengan ROW_NUMBER() seperti pada contoh sebelumnya.

Kami juga dapat mengganti SELECT * dengan DELETE untuk menghapus duplikat.

Opsi 7

Dan terakhir, inilah satu opsi lagi untuk mengembalikan duplikat:

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

Hasil:

+-------+-----------+----------+-------+-----------+----------+
| DogId | FirstName | LastName | DogId | FirstName | LastName |
+-------+-----------+----------+-------+-----------+----------+
|     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. Menggunakan Mesin Penyimpanan MySQL yang Berbeda dalam Desain Basis Data

  2. Menduplikasi tabel MySQL, indeks, dan data

  3. Mengapa mysqli memberikan perintah tidak sinkron?

  4. Mac OS X - EnvironmentError:mysql_config tidak ditemukan

  5. Dukungan JSON asli di MYSQL 5.7 :apa pro dan kontra dari tipe data JSON di MYSQL?