Extrageți doar primul din unitatea de înregistrare în care este duplicată valoarea coloanei specificate
Î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 | ID1 | ID2 |
---|---|---|
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 | ID1 | ID2 |
---|---|---|
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)
)