sql >> Databasteknik >  >> RDS >> Oracle

6 sätt att välja dubbletter av rader i Oracle

Följande exempel returnerar dubbletter av rader från en Oracle Database-tabell.

Exempeldata

Anta att vi har en tabell med följande 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 två första raderna är dubbletter, liksom de tre sista raderna. I det här fallet innehåller dubblettraderna dubblettvärden över alla kolumner, inklusive ID-kolumnen.

Alternativ 1

Vi kan använda följande fråga för att se hur många rader som är dubbletter:

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 grupperade raderna efter alla kolumner och returnerade radantalet för varje grupp. Varje rad med ett antal större än 1 är en dubblett.

Vi kan sortera efter antal i fallande ordning, så att raderna med flest dubbletter visas 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

Alternativ 2

Om vi ​​bara vill ha dubblettraderna listade kan vi använda koden HAVING sats för att endast returnera rader med ett antal större än 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

Alternativ 3

Ett annat alternativ är att använda ROW_NUMBER() fönsterfunktion:

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 satsen delar resultatuppsättningen som produceras av FROM sats i partitioner som funktionen tillämpas på. När vi anger partitioner för resultatuppsättningen, gör varje partition att numreringen börjar om igen (dvs. numreringen börjar på 1 för den första raden i varje partition).

Alternativ 4

Vi kan använda ovanstående fråga som ett vanligt tabelluttryck:

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

Detta returnerar bara överflödiga rader från matchande dubbletter. Så om det finns två identiska rader returneras en av dem. Om det finns tre identiska rader returneras två, och så vidare.

Alternativ 5

Eftersom vår tabell inte innehåller en primärnyckelkolumn kan vi dra fördel av Oracles rowid pseudokolumn:

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å här fungerar det är att varje rad i en Oracle-databas har en rowid pseudokolumn som returnerar adressen till raden. rowid är en unik identifierare för rader i tabellen, och vanligtvis identifierar dess värde unikt en rad i databasen. Det är dock viktigt att notera att rader i olika tabeller som är lagrade tillsammans i samma kluster kan ha samma rowid .

En fördel med exemplet ovan är att vi kan ersätta SELECT * med DELETE för att de-dupera tabellen.

Alternativ 6

Och slutligen, här är ett annat alternativ som använder rowid pseudokolumn:

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

Samma resultat som föregående exempel.

Som med föregående exempel kan vi ersätta SELECT * med DELETE för att ta bort dubbletter av rader från tabellen.


  1. 11 sätt att hitta dubbletter av rader medan du ignorerar den primära nyckeln i SQLite

  2. Bevilja alla på ett specifikt schema i db till en grupproll i PostgreSQL

  3. Oracle PL/SQL:Skapa DML-paket online

  4. Försöker få in egendom av icke-objekt