Extrahera endast den första från postenheten där värdet för den angivna kolumnen dupliceras
Normalt, när du bara extraherar en dubblettpost, är distinct
det första som kommer att tänka på att jag tänker,
distinct
Du kan inte ange en dubblettkolumn och en annan kolumn som du vill hämta samtidigt.
distinct
Dessutom matchar den inte det här kravet eftersom den innehåller icke-dubblettposter i extraheringen.
Jag tror inte att du kan förstå vad du vill göra med bara titeln, så låt oss använda en exempelpost som exempel. Vad jag vill göra är följande extraktionsresultat.
ID-namn | |
---|---|
1 | Namn 1 |
2 | Namn 2 |
3 | Namn 3 |
3 | Namn 3@example.com |
4 | Namn 4 Namn 4@example.com |
4 | Namn 4@example.com |
4 | Namn 4@example.com |
Få det enligt följande:
ID-namn | |
---|---|
3 | Namn 3@example.com |
4 | Namn 4@example.com |
ID 1 och 2 ingår inte eftersom de inte är dubbletter. ID 3 och 4 är dubbletter, så en av dem hämtas. Den här gången får vi dock inte den första posten i DB-lagringsordningen. Anta dessutom att du vill ha den första raden i namnet i prioritetsordning under villkoren att "Namnet innehåller ett @-tecken" och "Namnet har ett litet antal tecken".
Ovanstående villkor kan erhållas med följande SQL. Vi använder dock underfrågor och har inte kontrollerat prestandan.
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)
)
Dubblettrader kontrolleras having
med och count
. group by
Nyckelkolumnen ska kontrolleras från utsidan, här ID
begränsas where
kolumnen med .
Prioritetsordningen för att hämta den första raden anges order by
av . charindex
Här och len
kontrollera om den innehåller det angivna tecknet och längden på strängen.
top
Allt du behöver göra är att hämta den första raden i varje dubblettpost i .
Ursprungligen är detta bra, men om det finns två eller flera poster med exakt samma värde, till exempel "ID: 4, Namn: Namn 4@example.com", kommer du oundvikligen att få två poster.
row_number
Därför läggs den till så att den kan identifieras för varje rad med , så att endast en post med exakt samma värde kan hämtas.
Om det är känt att exakt samma post inte finns, tror jag row_number
att det skulle vara bättre att kontrollera värdena på de befintliga posterna utan att lägga till .
Om det finns flera nycklar som ska kontrolleras för dubbletter kan du öka antalet nyckelkolumner för varje. Tänk dig till exempel följande post: Kolumnerna som ska kontrolleras för dubbletter är "ID1" och "ID2".
ID1 | ID2 | Namn |
---|---|---|
1 | 1 | Namn 1 |
2 | 1 | Namn 2 |
3 | 1 | Namn 31 |
3 | 2 | Namn 32 |
4 | 1 | Namn41 |
4 | 2 | Namn42 |
4 | 2 | Namn 4@example.com |
5 | 1 | Namn 555@example.com |
5 | 1 | Namn 55@example.com |
5 | 2 | Namn 5@example.com |
6 | 1 | Namn 6 |
6 | 1 | Namn 66@example.com |
6 | 2 | Namn 6 |
6 | 2 | Namn 6 |
Förvärvsresultatet är följande.
ID1 | ID2 | Namn |
---|---|---|
4 | 2 | Namn 4@example.com |
5 | 1 | Namn 55@example.com |
6 | 1 | Namn 66@example.com |
6 | 2 | Namn 6 |
SQL ser ut så här: Du kan helt enkelt öka den del där nyckelkolumnen angavs.
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)
)