Wybierz instrukcję, aby znaleźć duplikaty w niektórych polach


415

Czy możesz mi pomóc z instrukcjami SQL w znajdowaniu duplikatów w wielu polach?

Na przykład w pseudo kodzie:

select count(field1,field2,field3) 
from table 
where the combination of field1, field2, field3 occurs multiple times

i z powyższego stwierdzenia, jeśli istnieje wiele wystąpień , chciałbym wybrać każdy rekord z wyjątkiem pierwszego .


3
twój pseudo kod jest niejednoznaczny, a ponadto nie definiujesz kolejności, według której nie chcesz pierwszego. proponuję podać przykładowe dane.
Nieuzasadniony

Odpowiedzi:


840

Aby uzyskać listę pól, dla których istnieje wiele rekordów, możesz użyć ...

select field1,field2,field3, count(*)
  from table_name
  group by field1,field2,field3
  having count(*) > 1

Sprawdź ten link, aby uzyskać więcej informacji na temat usuwania wierszy.

http://support.microsoft.com/kb/139444

Edycja: Jak wspomnieli inni użytkownicy, przed zastosowaniem metody opisanej w powyższym linku powinno istnieć kryterium decydujące o tym, jak zdefiniować „pierwsze rzędy”. Na tej podstawie musisz użyć zamówienia według klauzuli i zapytania podrzędnego, jeśli to konieczne. Jeśli możesz opublikować przykładowe dane, to naprawdę by pomogło.


42

Wspominasz o „pierwszym”, więc zakładam, że masz jakieś uporządkowanie danych. Załóżmy, że twoje dane są uporządkowane według jakiegoś pola ID.

Ten SQL powinien dać ci zduplikowane wpisy, z wyjątkiem pierwszego. Zasadniczo wybiera wszystkie wiersze, dla których istnieje inny wiersz z (a) tymi samymi polami i (b) o niższym ID. Wydajność nie będzie świetna, ale może rozwiązać Twój problem.

SELECT A.ID, A.field1, A.field2, A.field3
  FROM myTable A
 WHERE EXISTS (SELECT B.ID
                 FROM myTable B
                WHERE B.field1 = A.field1
                  AND B.field2 = A.field2
                  AND B.field3 = A.field3
                  AND B.ID < A.ID)

17

To zabawne rozwiązanie z SQL Server 2005, które lubię. Zakładam, że przez „dla każdego rekordu oprócz pierwszego” masz na myśli inną kolumnę „id”, której możemy użyć do zidentyfikowania, który wiersz jest „pierwszy”.

SELECT id
    , field1
    , field2
    , field3
FROM
(
    SELECT id
        , field1
        , field2
        , field3
        , RANK() OVER (PARTITION BY field1, field2, field3 ORDER BY id ASC) AS [rank]
    FROM table_name
) a
WHERE [rank] > 1

Właśnie zauważyłem znacznik SQL Server 2008. Cieszę się, że moja sugestia jest nadal aktualna.
Nick Vaccaro,

1
Doskonałe rozwiązanie, ponieważ zwraca również wiersze, które trzeba będzie usunąć z omawianej tabeli
Realto619,

1
pomaga myśleć o liście pól PARTITION BY jako wykazu pól PK
bkwdesign

6

Aby zobaczyć zduplikowane wartości:

with MYCTE  as (
    select row_number() over ( partition by name  order by name) rown, *
    from tmptest  
    ) 
select * from MYCTE where rown <=1

3

Jeśli używasz programu SQL Server 2005 lub nowszego (a znaczniki pytania wskazują SQL Server 2008), możesz użyć funkcji rankingu, aby zwrócić zduplikowane rekordy po pierwszym, jeśli użycie sprzężeń jest z jakiegoś powodu mniej pożądane lub niepraktyczne. Poniższy przykład pokazuje to w działaniu, gdzie działa również z wartościami null w badanych kolumnach.

create table Table1 (
 Field1 int,
 Field2 int,
 Field3 int,
 Field4 int 
)

insert  Table1 
values    (1,1,1,1)
        , (1,1,1,2)
        , (1,1,1,3)
        , (2,2,2,1)
        , (3,3,3,1)
        , (3,3,3,2)
        , (null, null, 2, 1)
        , (null, null, 2, 3)

select    *
from     (select      Field1
                    , Field2
                    , Field3
                    , Field4
                    , row_number() over (partition by   Field1
                                                      , Field2
                                                      , Field3
                                         order by       Field4) as occurrence
          from      Table1) x
where     occurrence > 1

Zauważ, że po uruchomieniu tego przykładu pierwszy rekord z każdej „grupy” jest wykluczony i że rekordy z wartościami null są obsługiwane poprawnie.

Jeśli nie masz dostępnej kolumny do porządkowania rekordów w grupie, możesz użyć kolumn podziału według jako kolumn uporządkowania według.


1
CREATE TABLE #tmp
(
    sizeId Varchar(MAX)
)

INSERT  #tmp 
    VALUES ('44'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46')


SELECT * FROM #tmp
DECLARE @SqlStr VARCHAR(MAX)

SELECT @SqlStr = STUFF((SELECT ',' + sizeId
              FROM #tmp
              ORDER BY sizeId
              FOR XML PATH('')), 1, 1, '') 


SELECT TOP 1 * FROM (
select items, count(*)AS Occurrence
  FROM dbo.Split(@SqlStr,',')
  group by items
  having count(*) > 1
  )K
  ORDER BY K.Occurrence DESC    

0

spróbuj tego zapytania, aby mieć liczbę osobno każdej instrukcji SELECT:

select field1,count(field1) as field1Count,field2,count(field2) as field2Counts,field3, count(field3) as field3Counts
from table_name
group by field1,field2,field3
having count(*) > 1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.