Estrai solo il primo dall'unità di record in cui viene duplicato il valore della colonna specificata

Pagina aggiornata :
Data di creazione della pagina :

Normalmente, quando si estrae un solo record duplicato, la prima cosa che viene in mente è distinct che penso: distinct non consente di specificare contemporaneamente una colonna duplicata e un'altra colonna che si desidera recuperare. Inoltre,distinct non soddisfa questo requisito perché include record non duplicati nell'estrazione.

Non credo che tu possa capire cosa vuoi fare con il titolo da solo, quindi usiamo un record di esempio come esempio. Quello che voglio fare è il seguente risultato di estrazione.

Nome ID
1 Nome 1
2 Nome 2
3 Nome 3
3 Nome 3@example.com
4 Nome 4 Nome 4@example.com
4 Nome 4@example.com
4 Nome 4@example.com

Ottenilo come segue:

Nome ID
3 Nome 3@example.com
4 Nome 4@example.com

Gli ID 1 e 2 non sono inclusi perché non sono duplicati. Gli ID 3 e 4 sono duplicati, quindi uno di essi viene recuperato. Tuttavia, questa volta, non otterremo il primo record nell'ordine di archiviazione del database. Inoltre, supponiamo di volere la prima riga del nome in ordine di priorità nelle condizioni in cui "Il nome contiene un segno @" e "Il nome ha un numero ridotto di caratteri".

La condizione di cui sopra può essere ottenuta con il seguente SQL. Tuttavia, stiamo utilizzando le sottoquery e non abbiamo controllato le prestazioni.

select
  *
from
  (select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
  select
    top(1) RowNum
  from
    (select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableSub
  where
        tableMain.ID = tableSub.ID
    and exists ( 
      select
        *
      from
        SampleTable
      where
        tableSub.ID = ID
      having
        count(*) >= 2
    )
  order by
    case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)

Le righe duplicate vengono having controllate con e count . group by La colonna chiave da controllare dall'esterno, qui ID la colonna è where ristretta di .

L'ordine di precedenza per il recupero della prima riga è order by specificato da . charindex Qui, e len controlla se contiene il carattere specificato e la lunghezza della stringa. top Tutto quello che devi fare è ottenere la prima riga di ogni record duplicato in .

Originariamente, questo va bene, ma se ci sono due o più record con esattamente lo stesso valore, come "ID: 4, Nome: Nome 4@example.com", otterrai inevitabilmente due record. row_number Pertanto, viene aggiunto in modo che possa essere identificato per ogni riga con , in modo che sia possibile recuperare un solo record con esattamente lo stesso valore. Se si sa che lo stesso identico record non esiste, penso row_number che sarebbe meglio controllare i valori dei record esistenti senza aggiungere .

Se sono presenti più chiavi da verificare la presenza di duplicati, è possibile aumentare il numero di colonne chiave per ciascuna. Si consideri, ad esempio, il seguente record: Le colonne da verificare la presenza di duplicati sono "ID1" e "ID2".

ID1Nome ID2
1 1 Nome 1
2 1 Nome 2
3 1 Nome 31
3 2 Nome 32
4 1 Nome41
4 2 Nome42
4 2 Nome 4@example.com
5 1 Nome 555@example.com
5 1 Nome 55@example.com
5 2 Nome 5@example.com
6 1 Nome 6
6 1 Nome 66@example.com
6 2 Nome 6
6 2 Nome 6

Il risultato dell'acquisizione è il seguente.

ID1Nome ID2
4 2 Nome 4@example.com
5 1 Nome 55@example.com
6 1 Nome 66@example.com
6 2 Nome 6

L'SQL è simile al seguente: È possibile aumentare semplicemente la parte in cui è stata specificata la colonna chiave.

select
  *
from
  (select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
  select
    top(1) RowNum
  from
    (select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableSub
  where
        tableMain.ID1 = tableSub.ID1
    and tableMain.ID2 = tableSub.ID2
    and exists ( 
      select
        *
      from
        SampleTable
      where
            tableSub.ID1 = ID1
        and tableSub.ID2 = ID2
      having
        count(*) >= 2
    )
  order by
    case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)