2013-08-29 9 views
6

I Szukano Find duplicate entries in a column i Oracle: find duplicate rows in select query, ale nie wydaje się uzyskać żadnej odpowiedzi ...Znajdź duplikaty w kolumnie Oracle SQL

Mam niektóre dane, które wygląda tak

columnA columnB columnC 
1111111 emailID1 true 
1111111 emailID2 false 
1111222 emailID3 true 
1111339 emailID4 true 
2384398 emailID5 true 

Chciałbym aby wyświetlać tylko te kolumny, która ma te same wartości w Columna ale może być różna w columnB i/lub C:

columnA columnB columnC 
1111111 emailID1 true 
1111111 emailID2 false 

Korzystanie z konieczności> 1 tak naprawdę nie wydaje się captu czy to są jakieś pomysły? Dzięki.

+0

Swoją drogą, szukam tego tylko na jednym stole, nie ma potrzeby łączenia. :) –

+0

niektóre z przedstawionych rozwiązań dotyczą * self join *, więc join * jest * poprawnym rozwiązaniem twojego problemu. –

Odpowiedz

0
SELECT T.columnA, S.columnB, S.columnC FROM 
(
SELECT columnA FROM someTable 
GROUP BY columnA 
HAVING COUNT(*) > 1 
) T INNER JOIN someTable S ON T.columnA = S.columnA 
7

Korzystanie having count(*) > 1 jest tylko jedna połowa układanki. Druga połowa otrzymuje odpowiednie wiersze.

Można to zrobić tak:

SELECT * 
FROM MyTable 
WHERE ColumnA IN (
    SELECT ColumnA FROM MyTable GROUP BY ColumnA HAVING COUNT(*) > 1 
) 
+0

+1, ale można to zrobić również przy połączeniu z sub-select, który będzie skalowany. – Bohemian

0

Można to zrobić za pomocą funkcji analitycznych. Znajdź min i max i powrotu wiersze gdzie są one różne:

select columnA, columnB, columnC 
from (select t.*, min(t.columnC) over (partition by columnA, columnB) as minC, 
      max(t.columnC) over (partition by columnA, columnB) as maxC 
     from t 
    ) t 
where minC <> maxC; 
5

Spróbuj tego:

SELECT t.* 
FROM (SELECT ColumnA FROM MyTable GROUP BY ColumnA HAVING COUNT(*) > 1) dups 
JOIN MyTable t ON t.ColumnA = dups.ColumnA 

Będzie dobrze skalować też, tak długo, jak indeks jest na ColumnA:

create index MyTable_ColumnA on MyTable(ColumnA); 

taki indeks byłby używany zarówno dla zapytania głównego, jak i zapytania wewnętrznego, co zapewnia bardzo dobrą wydajność.

+1

+1 Chociaż podoba mi się wygląd "IN" nieco lepiej, to w 100% zgadzam się, że "JOIN" sprawia, że ​​mniej zależą od optymalizatora. – dasblinkenlight

+0

Niestety nie dołączam do 2 tabel ... –

+1

Oczywiście nie - w tym przypadku propozycja polega na dołączeniu do jednego stołu. Zapytanie wewnętrzne identyfikuje duplikaty wierszy, zapytanie zewnętrzne gromadzi inne kolumny, które chciałeś w wyniku. –

1

I jak zwykle, aby uniknąć uderzenia w tabeli więcej niż raz w zapytaniu - to będzie działać dobrze nawet bez indeksu - robi tylko jedno skanowanie nad stołem:

SELECT columnA, columnB, columnC 
FROM (SELECT mytable.* 
      ,COUNT(*) OVER (PARTITION BY columnA) countA 
     FROM mytable) 
WHERE countA > 1 
0

Ten wątek może być stary, ale go Warto zaktualizować każdemu lepsze/wydajne rozwiązanie, aby znaleźć duplikaty rekordów. Możesz użyć partycji, aby znaleźć duplikaty rekordów na pasujących kolumnach (tyle kolumn, ile potrzebujesz bez wewnętrznego łączenia).

SELECT * 
FROM (
     SELECT t.*, ROW_NUMBER() OVER (PARTITION BY column1, column2 ORDER BY your_key_column) AS duplicate_count 
     FROM yourtable t 
     ) 
WHERE duplicate_count > 1 --get duplicate records for the matching value in column1 and column2 

Zobacz oryginalną odpowiedź od @Quassnoi pod numerem here. Dzięki za jego, bardzo sprytne rozwiązanie przy użyciu partycji.

0

Jeśli szukasz wpisami z unikalnymi identyfikatorami w swojej bazie danych, gdzie mogą wystąpić wiele kluczy w kolumnie, a następnie w prosty sposób znalezienie ich jest utworzenie dwóch tabel jak exlplained poniżej:

tutaj: ticketid jest podstawowym klucz, TKTNUMBER może wystąpić wiele razy.

CREATE TABLE TEMP 
(
    TICKETID FLOAT, 
    TKTNUMBER FLOAT 
); 

CREATE TABLE TEMP2 
(
    TKTNUMBER FLOAT, 
    COUNTER  INTEGER 
); 

Put we wszystkich ticketid i TKTNUMBER poprzez patrząc tylko na TKTNUMBERS z count (TKTNUMBER)> 1:

INSERT INTO TEMP 
    SELECT 
     TICKETID, 
     TKTNUMBER 
    FROM YOUR_TABLE 
    WHERE TKTNUMBER IN ( 
      SELECT TKTNUMBER 
      FROM YOUR_TABLE 
      HAVING COUNT (TKTNUMBER) > 1 
      GROUP BY TKTNUMBER); 

Wreszcie, aby zobaczyć licznik, umieścić w TKTNUMBER i policzyć sama sposób jak powyżej:

INSERT INTO TEMP2 
    SELECT 
     TKTNUMBER, 
     COUNT (TKTNUMBER) AS COUNTER 
    FROM YOUR_TABLE 
    HAVING COUNT (TKTNUMBER) > 1 
    GROUP BY TKTNUMBER 
    ORDER BY 2 DESC 

można wybrać w następujący sposób (poprzez łączenie dwóch tabel na tktnumber):

SELECT 
    T1.TICKETID, 
    T1.TKTNUMBER, 
    T2.COUNTER 
FROM 
    TEMP T1 INNER JOIN 
    TEMP2 T2 ON 
     T2.TKTNUMBER = T1.TKTNUMBER 
ORDER BY T2.COUNTER DESC