Extrahera endast den första från postenheten där värdet för den angivna kolumnen dupliceras

Sidan uppdaterad :
Datum för skapande av sida :

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