sql >> Databáze >  >> RDS >> MariaDB

7 způsobů, jak vrátit duplicitní řádky, které mají primární klíč v MariaDB

Zde je sedm způsobů, jak vrátit duplicitní řádky v MariaDB, když tyto řádky mají primární klíč nebo jiný sloupec jedinečného identifikátoru.

Proto duplicitní řádky sdílejí přesně stejné hodnoty ve všech sloupcích kromě sloupce s jedinečným identifikátorem.

Ukázková data

Pro naše příklady použijeme následující data:

SELECT * FROM Dogs;

Výsledek:

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

První dva řádky jsou duplikáty (kromě DogId sloupec, který je primárním klíčem tabulky a obsahuje jedinečnou hodnotu ve všech řádcích). Poslední tři řádky jsou také duplikáty (kromě DogId sloupec).

Sloupec primárního klíče zajišťuje, že neexistují žádné duplicitní řádky, což je obvykle dobrá věc v RDBMS. Z definice to však znamená, že neexistují žádné duplikáty. V našem případě je sloupec primárního klíče inkrementální číslo a jeho hodnota nemá žádný význam a není významná. Pokud tedy chceme najít duplikáty ve sloupcích, které jsou, musíme tento řádek ignorovat významný.

Možnost 1

Můžeme použít GROUP BY klauzuli k seskupení sloupců podle jejich významných sloupců a poté použijte funkci COUNT() funkce, která vrátí počet identických řádků:

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

Výsledek:

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

Podařilo se nám vyloučit sloupec primárního klíče tím, že jsme jej vynechali v našem dotazu.

Výsledek nám říká, že existují dva řádky obsahující Bark Smith a tři řádky obsahující Wag Johnson. Jedná se o duplikáty (nebo triplikáty v případě Waga Johnsona). Další dva řádky nemají žádné duplikáty.

Možnost 2

Neduplikáty můžeme z výstupu vyloučit pomocí HAVING klauzule:

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

Výsledek:

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

Možnost 3

Je také možné zkontrolovat duplikáty na zřetězených sloupcích. Můžeme například použít CONCAT() funkci pro spojení našich dvou sloupců použijte DISTINCT klíčové slovo, abyste získali odlišné hodnoty, pak použijte COUNT() funkce, která vrátí počet:

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

Výsledek:

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

Možnost 4

Můžeme použít ROW_NUMBER() pomocí funkce PARTITION BY klauzule:

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

Výsledek:

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

Tím se vytvoří nový sloupec s číslem řádku, které se zvýší pokaždé, když je duplikát, ale znovu se resetuje, když existuje jedinečný řádek.

V tomto případě výsledky neseskupujeme, což znamená, že vidíme každý duplicitní řádek, včetně sloupce s jedinečným identifikátorem.

Možnost 5

Předchozí příklad můžeme také použít jako běžný tabulkový výraz ve větším dotazu:

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;

Výsledek:

+-------+-----------+----------+------------+
| DogId | FirstName | LastName | Row_Number |
+-------+-----------+----------+------------+
|     2 | Bark      | Smith    |          2 |
|     5 | Wag       | Johnson  |          2 |
|     7 | Wag       | Johnson  |          3 |
+-------+-----------+----------+------------+

Tím se z výstupu vyloučí neduplikáty a z výstupu se vyloučí jeden řádek každého duplikátu.

Tento dotaz lze použít jako předchůdce operace odstranění duplikace. Může nám ukázat, co bude smazáno, pokud se rozhodneme smazat duplikáty. K odstranění duplicit v tabulce stačí nahradit poslední SELECT * pomocí DELETE .

Možnost 6

Zde je stručnější způsob, jak získat stejný výstup jako v předchozím příkladu:

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

Výsledek:

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

Tento příklad nevyžaduje generování vlastního samostatného čísla řádku.

Můžeme nahradit SELECT * pomocí DELETE k odstranění duplikátů.

Možnost 7

A nakonec je zde další možnost pro vrácení duplikátů:

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

Výsledek:

+-------+-----------+----------+-------+-----------+----------+
| 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. 4 způsoby, jak zobrazit seznam všech pohledů v databázi SQL Server

  2. PostgreSQL index na JSON

  3. Řešení pro ORA-00997:nelegální použití datového typu LONG

  4. Jak uložit hodnoty NULL do polí data a času v MySQL?