sql >> Database teknologi >  >> RDS >> Oracle

6 måder at vælge dublerede rækker i Oracle

Følgende eksempler returnerer dublerede rækker fra en Oracle-databasetabel.

Eksempeldata

Antag, at vi har en tabel med følgende data:

SELECT * FROM Pets;

Resultat:

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

De første to rækker er dubletter, ligesom de sidste tre rækker. I dette tilfælde indeholder de duplikerede rækker dublerede værdier på tværs af alle kolonner, inklusive ID-kolonnen.

Valgmulighed 1

Vi kan bruge følgende forespørgsel til at se, hvor mange rækker der er dubletter:

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

Resultat:

PETID	PETNAME	PETTYPE	Count
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	3

Vi grupperede rækkerne efter alle kolonner og returnerede rækkeantallet for hver gruppe. Enhver række med et antal større end 1 er en dublet.

Vi kan bestille det efter antal i faldende rækkefølge, så rækkerne med flest dubletter vises først:

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

Resultat:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1

Valgmulighed 2

Hvis vi kun vil have de duplikerede rækker på listen, kan vi bruge koden HAVING klausul for kun at returnere rækker med et antal større end 1:

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

Resultat:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2

Valgmulighed 3

En anden mulighed er at bruge ROW_NUMBER() vinduesfunktion:

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

Resultat:

PETID	PETNAME	PETTYPE	RN
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 klausul deler resultatsættet produceret af FROM klausul i partitioner, som funktionen anvendes på. Når vi angiver partitioner for resultatsættet, får hver partition nummereringen til at starte forfra (dvs. nummereringen starter ved 1 for den første række i hver partition).

Valgmulighed 4

Vi kan bruge ovenstående forespørgsel som et almindeligt tabeludtryk:

WITH cte AS 
    (
        SELECT 
            PetId,
            PetName,
            PetType,
            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;

Resultat:

PETID	PETNAME	PETTYPE	ROW_NUMBER
1	Wag	Dog	2
4	Bark	Dog	2
4	Bark	Dog	3

Dette returnerer kun de overskydende rækker fra de matchende dubletter. Så hvis der er to identiske rækker, returnerer den en af ​​dem. Hvis der er tre ens rækker, returnerer det to, og så videre.

Valgmulighed 5

Da vores tabel ikke indeholder en primær nøglekolonne, kan vi drage fordel af Oracles rowid pseudokolonne:

SELECT * FROM Pets
WHERE EXISTS (
  SELECT 1 FROM Pets p2 
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
  AND Pets.rowid > p2.rowid
);

Resultat:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Sådan fungerer det, at hver række i en Oracle-database har en rowid pseudokolonne, der returnerer adressen på rækken. rowid er en unik identifikator for rækker i tabellen, og normalt identificerer dens værdi entydigt en række i databasen. Det er dog vigtigt at bemærke, at rækker i forskellige tabeller, der er gemt sammen i den samme klynge, kan have den samme rowid .

En fordel ved ovenstående eksempel er, at vi kan erstatte SELECT * med DELETE for at de-dupere bordet.

Valgmulighed 6

Og endelig, her er en anden mulighed, der bruger rowid pseudokolonne:

SELECT * FROM Pets
WHERE rowid > (
  SELECT MIN(rowid) FROM Pets p2  
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
);

Resultat:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Samme resultat som det foregående eksempel.

Som med det foregående eksempel kan vi erstatte SELECT * med DELETE for at fjerne duplikerede rækker fra tabellen.


  1. Transform ODBC-data i CloverDX

  2. Sådan genereres scripts for at føje standardbegrænsninger til kolonne i flere tabeller i SQL Server-database - SQL Server / TSQL vejledning del 94

  3. Hvordan kan jeg opdatere et felt af min spinner med brugerinput i EditText

  4. Postgresql-udtræk sidste række for hvert id