Extrageți doar primul din unitatea de înregistrare în care este duplicată valoarea coloanei specificate

Pagina actualizată :
Data creării paginii :

În mod normal, atunci când extrag o singură înregistrare duplicată, primul lucru care îmi vine în minte este distinct că mă gândesc: distinct nu vă permite să specificați o coloană dublă și o altă coloană pe care doriți să o recuperați în același timp. În plus,distinct nu corespunde acestei cerințe, deoarece include înregistrări neduplicate în extracție.

Nu cred că poți înțelege ce vrei să faci doar cu titlul, așa că haideți să folosim un exemplu de înregistrare. Ceea ce vreau să fac este următorul rezultat al extracției.

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

Ia-l după cum urmează:

Nume ID
3 Nume 3@example.com
4 Nume 4@example.com

ID-urile 1 și 2 nu sunt incluse deoarece nu sunt duplicate. ID-urile 3 și 4 sunt duplicate, deci unul dintre ele este recuperat. Cu toate acestea, de data aceasta, nu vom obține prima înregistrare din ordinea de stocare DB. În plus, să presupunem că doriți ca prima linie a numelui să fie în ordinea priorității în condițiile în care "Numele conține un marcaj @" și "Numele are un număr mic de caractere".

Condiția de mai sus poate fi obținută cu următorul SQL. Cu toate acestea, folosim subinterogări și nu am verificat performanța.

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)
)

Rândurile duplicate sunt having verificate cu și count . group by Coloana cheie trebuie verificată din exterior, aici ID coloana este where restrânsă cu .

Ordinea de prioritate pentru preluarea primului rând este order by specificată de . charindex Aici și len verificați dacă conține caracterul specificat și lungimea șirului. top Tot ce trebuie să faceți este să obțineți primul rând al fiecărei înregistrări duplicate în .

Inițial, acest lucru este în regulă, dar dacă există două sau mai multe înregistrări cu exact aceeași valoare, cum ar fi "ID: 4, Nume: Nume 4@example.com", veți obține inevitabil două înregistrări. row_number Prin urmare, este adăugat astfel încât să poată fi identificat pentru fiecare rând cu , astfel încât să poată fi preluată o singură înregistrare cu exact aceeași valoare. Dacă se știe că exact aceeași înregistrare nu există, row_number cred că ar fi mai bine să verificați valorile înregistrărilor existente fără a adăuga .

Dacă există mai multe chei care trebuie verificate pentru duplicate, puteți crește numărul de coloane cheie pentru fiecare. De exemplu, luați în considerare următoarea înregistrare: Coloanele care trebuie verificate pentru duplicate sunt "ID1" și "ID2".

Nume ID1ID2
1 1 Nume 1
2 1 Nume 2
3 1 Nume 31
3 2 Nume 32
4 1 Nume41
4 2 Nume42
4 2 Nume 4@example.com
5 1 Nume 555@example.com
5 1 Nume 55@example.com
5 2 Nume 5@example.com
6 1 Nume 6
6 1 Nume 66@example.com
6 2 Nume 6
6 2 Nume 6

Rezultatul achiziției este următorul.

Nume ID1ID2
4 2 Nume 4@example.com
5 1 Nume 55@example.com
6 1 Nume 66@example.com
6 2 Nume 6

SQL-ul arată astfel: Puteți pur și simplu să măriți partea în care a fost specificată coloana cheie.

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)
)