sql >> Databáze >  >> RDS >> Sqlserver

4 způsoby, jak zkontrolovat duplicitní řádky na serveru SQL

Zde jsou čtyři metody, které můžete použít k nalezení duplicitních řádků na serveru SQL Server.

„Duplicitními řádky“ mám na mysli dva nebo více řádků, které sdílejí přesně stejné hodnoty ve všech sloupcích.

Ukázková data

Předpokládejme, že máme tabulku s následujícími údaji:

SELECT * FROM Pets;

Výsledek:

+---------+-----------+-----------+
| PetId   | PetName   | PetType   |
|---------+-----------+-----------|
| 1       | Wag       | Dog       |
| 1       | Wag       | Dog       |
| 2       | Scratch   | Cat       |
| 3       | Tweet     | Bird      |
| 4       | Bark      | Dog       |
| 4       | Bark      | Dog       |
| 4       | Bark      | Dog       |
+---------+-----------+-----------+

Vidíme, že první dva řádky jsou duplikáty, stejně jako poslední tři řádky.

Možnost 1

K vrácení informací o duplicitních řádcích můžeme použít následující dotaz:

SELECT 
    DISTINCT PetId, 
    COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;

Výsledek:

+---------+---------+
| PetId   | Count   |
|---------+---------|
| 1       | 2       |
| 2       | 1       |
| 3       | 1       |
| 4       | 3       |
+---------+---------+

Můžeme rozšířit SELECT seznam, který v případě potřeby obsahuje další sloupce:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

Výsledek:

+---------+-----------+-----------+---------+
| PetId   | PetName   | PetType   | Count   |
|---------+-----------+-----------+---------|
| 1       | Wag       | Dog       | 2       |
| 2       | Scratch   | Cat       | 1       |
| 3       | Tweet     | Bird      | 1       |
| 4       | Bark      | Dog       | 3       |
+---------+-----------+-----------+---------+

Pokud má tabulka jedinečný identifikátor, můžeme tento sloupec z dotazu jednoduše odstranit. Pokud například předpokládáme, že PetId je ve skutečnosti sloupec primárního klíče, který obsahuje jedinečné ID, mohli bychom spustit následující dotaz, abychom vrátili všechny řádky, které jsou duplicitní, nepočítaje sloupec primárního klíče:

SELECT 
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetName,
    PetType
ORDER BY PetName;

Výsledek:

+-----------+-----------+---------+
| PetName   | PetType   | Count   |
|-----------+-----------+---------|
| Bark      | Dog       | 3       |
| Scratch   | Cat       | 1       |
| Tweet     | Bird      | 1       |
| Wag       | Dog       | 2       |
+-----------+-----------+---------+

Možnost 2

Pokud chceme vrátit pouze skutečné duplicitní řádky, můžeme přidat HAVING klauzule:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY PetId;

Výsledek:

+---------+-----------+-----------+---------+
| PetId   | PetName   | PetType   | Count   |
|---------+-----------+-----------+---------|
| 1       | Wag       | Dog       | 2       |
| 4       | Bark      | Dog       | 3       |
+---------+-----------+-----------+---------+

Možnost 3

Dalším způsobem, jak to udělat, je použít ROW_NUMBER() pomocí funkce PARTITION BY klauzule k očíslování výstupu sady výsledků.

SELECT 
    *, 
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS Row_Number
FROM Pets;

Výsledek:

+---------+-----------+-----------+--------------+
| PetId   | PetName   | PetType   | Row_Number   |
|---------+-----------+-----------+--------------|
| 1       | Wag       | Dog       | 1            |
| 1       | Wag       | Dog       | 2            |
| 2       | Scratch   | Cat       | 1            |
| 3       | Tweet     | Bird      | 1            |
| 4       | Bark      | Dog       | 1            |
| 4       | Bark      | Dog       | 2            |
| 4       | Bark      | Dog       | 3            |
+---------+-----------+-----------+--------------+

PARTITION BY klauzule rozděluje sadu výsledků vytvořenou FROM klauzule do oddílů, na které je funkce aplikována. Když určíme oddíly pro sadu výsledků, každý oddíl způsobí, že číslování začne znovu (tj. číslování začne na 1 pro první řádek v každém oddílu).

Možnost 4

Pokud chceme, aby byly vráceny pouze přebytečné řádky z odpovídajících duplikátů, můžeme použít výše uvedený dotaz jako společný tabulkový výraz, například takto:

WITH CTE AS 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
SELECT * FROM CTE WHERE Row_Number <> 1;

Výsledek:

+---------+-----------+-----------+--------------+
| PetId   | PetName   | PetType   | Row_Number   |
|---------+-----------+-----------+--------------|
| 1       | Wag       | Dog       | 2            |
| 4       | Bark      | Dog       | 2            |
| 4       | Bark      | Dog       | 3            |
+---------+-----------+-----------+--------------+

Jednou z výhod toho je, že můžeme odstranit duplicitní řádky jednoduše přepnutím SELECT * na DELETE (na posledním řádku).

Můžeme tedy použít výše uvedený kód, abychom viděli, které řádky budou smazány, a když jsme spokojeni s tím, že smažeme správné řádky, můžeme jej přepnout na DELETE příkaz k jejich skutečnému smazání.

Takhle:

WITH CTE AS 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
DELETE FROM CTE WHERE Row_Number <> 1;

  1. SQL Server Internals:Problematic Operators Pt. I – Skenování

  2. Možnosti cloudového zálohování pro PostgreSQL

  3. SQL Server TempDB Monitoring pomocí Dynamic Management Views (DMV)

  4. Algoritmus, aby se zabránilo vkládání SQL na MSSQL Server z kódu C#?