sql >> Database >  >> RDS >> Oracle

11 manieren om dubbele rijen te vinden die een primaire sleutel hebben in Oracle

Hier zijn elf opties voor het retourneren van dubbele rijen in Oracle Database wanneer die rijen een primaire sleutel of een andere unieke identificatiekolom hebben en u deze wilt negeren.

Voorbeeldgegevens

We gebruiken de volgende gegevens voor onze voorbeelden:

SELECT * FROM Dogs;

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
1 Bark Smith
2 Bark Smith
3 Inslag Jones
4 Kemmel Robinson
5 Kwispelen Johnson
6 Kwispelen Johnson
7 Kwispelen Johnson

De eerste twee rijen zijn duplicaten en de laatste drie rijen zijn duplicaten. De dubbele rijen delen exact dezelfde waarden in alle kolommen, met uitzondering van hun primaire sleutel/unieke ID-kolom.

De primaire sleutelkolom zorgt ervoor dat er geen dubbele rijen zijn, wat een goede gewoonte is in RDBMS'en, omdat primaire sleutels helpen de gegevensintegriteit af te dwingen. Maar het feit dat primaire sleutels unieke waarden bevatten, betekent dat we die kolom moeten negeren bij het zoeken naar duplicaten.

In onze tabel hierboven is de primaire sleutelkolom een ​​oplopend getal, en de waarde ervan heeft geen betekenis en is niet significant. We kunnen daarom de gegevens van die kolom negeren bij het zoeken naar duplicaten.

Optie 1

Dit is onze eerste optie voor het retourneren van duplicaten:

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

Resultaat:

FIRSTNAME Achternaam COUNT
Kwispelen Johnson 3
Borst Smith 2
Kemmel Robinson 1
Inslag Jones 1

Hier hebben we onze query gemaakt met de GROUP BY clausule zodat de uitvoer wordt gegroepeerd op de relevante kolommen. We gebruikten ook de COUNT() functie om het aantal identieke rijen te retourneren. En we hebben het gesorteerd in aflopende volgorde, zodat de duplicaten eerst verschijnen.

Het resultaat vertelt ons dat er drie rijen zijn met Wag Johnson en twee rijen met Bark Smith. Dit zijn duplicaten (of drievoud in het geval van Wag Johnson). De andere twee rijen hebben geen dubbele rijen.

Optie 2

We kunnen de HAVING . toevoegen clausule toe aan ons vorige voorbeeld om niet-duplicaten van de uitvoer uit te sluiten:

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

Resultaat:

FIRSTNAME Achternaam COUNT
Kwispelen Johnson 3
Borst Smith 2

Optie 3

We kunnen ook controleren op duplicaten op aaneengeschakelde kolommen. In dit geval gebruiken we de DISTINCT zoekwoord om verschillende waarden te krijgen, gebruik dan de COUNT() functie om de telling terug te geven:

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

Resultaat:

HONDENNAAM COUNT
Wag Johnson 3
Bark Smith 2
Ruff Robinson 1
Woef Jones 1

Optie 4

Elke rij in Oracle heeft een rowid pseudokolom die het adres van de rij retourneert. De rowid is een unieke id voor rijen in de tabel, en gewoonlijk identificeert de waarde ervan een rij in de database op unieke wijze (hoewel het belangrijk is op te merken dat rijen in verschillende tabellen die samen in hetzelfde cluster zijn opgeslagen dezelfde rowid ).

Hoe dan ook, we kunnen een query maken die de rowid . gebruikt als we willen:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
);

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith
6 Kwispelen Johnson
7 Kwispelen Johnson

We zouden de SELECT * . kunnen vervangen met VERWIJDEREN om een ​​ontdubbelingsoperatie op de tafel uit te voeren.

Merk op dat we de DogId . hadden kunnen gebruiken kolom (onze primaire sleutel) in plaats van de rowid als we wilden. Dat gezegd hebbende, de rowid kan handig zijn als u de primaire sleutelkolom om de een of andere reden niet kunt gebruiken, of als de tabel geen primaire sleutel heeft.

Optie 5

Hier is nog een zoekopdracht die de rowid . gebruikt :

SELECT * FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith
6 Kwispelen Johnson
7 Kwispelen Johnson

Net als bij het vorige voorbeeld kunnen we de SELECT * . vervangen met VERWIJDEREN om de dubbele rijen te verwijderen.

Optie 6

De twee rowid bovenstaande opties zijn geweldig als u de primaire sleutel in uw zoekopdracht volledig moet negeren (of als u helemaal geen primaire sleutelkolom heeft). Maar zoals vermeld, is er nog steeds de mogelijkheid om rowid te vervangen met de primaire sleutelkolom – in ons geval de DogId kolom:

SELECT * FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
);

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith
6 Kwispelen Johnson
7 Kwispelen Johnson

Optie 7

En hier is de andere vraag met de rowid vervangen door de DogId kolom:

SELECT * FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith
6 Kwispelen Johnson
7 Kwispelen Johnson

Optie 8

Een andere manier om duplicaten te vinden is door de ROW_NUMBER() . te gebruiken vensterfunctie:

SELECT 
    DogId,
    FirstName,
    LastName,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS row_num
FROM Dogs;

Resultaat:

HONDEN-ID FIRSTNAME Achternaam ROW_NUM
1 Bark Smith 1
2 Bark Smith 2
4 Kemmel Robinson 1
7 Kwispelen Johnson 1
5 Kwispelen Johnson 2
6 Kwispelen Johnson 3
3 Inslag Jones 1

De PARTITIE . gebruiken clausule resulteert in het toevoegen van een nieuwe kolom, met een rijnummer dat wordt verhoogd elke keer dat er een duplicaat is, maar opnieuw wordt ingesteld wanneer er een unieke rij is.

In dit geval groeperen we de resultaten niet, wat betekent dat we elke dubbele rij kunnen zien, inclusief de unieke ID-kolom.

Optie 9

We kunnen het vorige voorbeeld ook gebruiken als een algemene tabeluitdrukking in een grotere query:

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

Resultaat:

HONDEN-ID FIRSTNAME Achternaam ROW_NUM
2 Bark Smith 2
5 Kwispelen Johnson 2
6 Kwispelen Johnson 3

Die zoekopdracht sluit niet-duplicaten uit van de uitvoer en sluit één rij van elk duplicaat uit van de uitvoer.

Optie 10

Hier is nog een manier om dezelfde uitvoer te krijgen als in het vorige voorbeeld:

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

Resultaat:

HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith
6 Kwispelen Johnson
7 Kwispelen Johnson

Dit voorbeeld gebruikt Oracle's MINUS operator, die alleen unieke rijen retourneert die worden geretourneerd door de eerste query, maar niet door de tweede.

De MIN operator is vergelijkbaar met de BEHALVE operator in andere DBMS'en, zoals SQL Server, MariaDB, PostgreSQL en SQLite.

Optie 11

Hier is nog een andere optie om duplicaten uit onze tabel te selecteren:

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

Resultaat:

HONDEN-ID FIRSTNAME Achternaam HONDEN-ID FIRSTNAME Achternaam
2 Bark Smith 1 Bark Smith
7 Kwispelen Johnson 5 Kwispelen Johnson
7 Kwispelen Johnson 6 Kwispelen Johnson

  1. Converteer 'tijd' naar 'datetimeoffset' in SQL Server (T-SQL-voorbeelden)

  2. Records ophalen waarbij de json-kolomsleutel null is

  3. Uitdagingsoplossingen voor generatorreeksen - deel 1

  4. Hoe maak je een SQL-weergave met SQLAlchemy?