Seleziona l'istruzione per trovare duplicati su determinati campi


415

Potete aiutarmi con le istruzioni SQL per trovare duplicati su più campi?

Ad esempio, nello pseudo codice:

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

e dall'affermazione sopra se ci sono più occorrenze vorrei selezionare ogni record tranne il primo .


3
il tuo pseudo codice è ambiguo, inoltre non definisci l'ordine in base al quale non vuoi il primo. ti suggerisco di fornire alcuni dati di esempio.
Unreason,

Risposte:


840

Per ottenere l'elenco dei campi per i quali sono presenti più record, è possibile utilizzare ..

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

Controlla questo link per ulteriori informazioni su come eliminare le righe.

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

Modifica: come menzionato dagli altri utenti, dovrebbe esserci un criterio per decidere come definire le "prime righe" prima di usare l'approccio nel link sopra. In base a ciò dovrai utilizzare una clausola order by e una query secondaria, se necessario. Se puoi pubblicare alcuni dati di esempio, sarebbe davvero di aiuto.


42

Citi "il primo", quindi presumo che tu abbia un qualche tipo di ordinamento sui tuoi dati. Supponiamo che i tuoi dati siano ordinati in base a qualche campo ID.

Questo SQL dovrebbe ottenere le voci duplicate ad eccezione della prima. In pratica, seleziona tutte le righe per le quali esiste un'altra riga con (a) gli stessi campi e (b) un ID inferiore. Le prestazioni non saranno eccezionali, ma potrebbe risolvere il tuo problema.

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

Questa è una soluzione divertente con SQL Server 2005 che mi piace. Suppongo che per "per ogni record tranne il primo", intendi che esiste un'altra colonna "id" che possiamo usare per identificare quale riga è "prima".

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

Ho appena notato il tag SQL Server 2008. Sono contento che il mio suggerimento sia ancora valido.
Nick Vaccaro,

1
Ottima soluzione perché restituisce anche le righe che dovranno essere eliminate dalla tabella in questione
Realto619

1
aiuta a pensare all'elenco dei campi PARTITION BY come a un elenco di campi PK
bkwdesign

6

Per visualizzare valori duplicati:

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

3

Se si utilizza SQL Server 2005 o versione successiva (e i tag per la domanda indicano SQL Server 2008), è possibile utilizzare le funzioni di classificazione per restituire i record duplicati dopo il primo se l'utilizzo dei join è meno desiderabile o poco pratico per qualche motivo. L'esempio seguente mostra questo in azione, dove funziona anche con valori null nelle colonne esaminate.

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

Si noti dopo aver eseguito questo esempio che il primo record di ogni "gruppo" è escluso e che i record con valori null sono gestiti correttamente.

Se non si dispone di una colonna disponibile per ordinare i record all'interno di un gruppo, è possibile utilizzare le colonne di partizione come colonne di ordine.


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

prova questa query per avere il conteggio separato di ciascuna istruzione 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.