Extrahujte pouze první z jednotek záznamu, ve kterém je hodnota zadaného sloupce duplikována

Stránky aktualizovány :
Datum vytvoření stránky :

Normálně, když extrahujete pouze jeden duplicitní záznam, první věc, která mě napadne, je distinct : distinct Neumožňuje zadat duplicitní sloupec a další sloupec, který chcete načíst současně. Navíc nesplňuje tento požadavek,distinct protože do extrakce zahrnuje neduplicitní záznamy.

Nemyslím si, že dokážete pochopit, co chcete dělat se samotným názvem, takže jako příklad použijme ukázkový záznam. Co chci udělat, je následující výsledek extrakce.

ID jméno
1 Název 1
2 Název 2
3 Název 3
3 Jméno 3@example.com
4 Jméno 4 Jméno 4@example.com
4 Jméno 4@example.com
4 Jméno 4@example.com

Získejte jej následovně:

ID jméno
3 Jméno 3@example.com
4 Jméno 4@example.com

ID 1 a 2 nejsou zahrnuta, protože se nejedná o duplicitní čísla. ID 3 a 4 jsou duplicitní, takže se načte jeden z nich. Tentokrát se však prvního záznamu v objednávce úložiště DB nedočkáme. Kromě toho předpokládejme, že chcete, aby první řádek názvu byl seřazen podle priority za podmínek, že "Název obsahuje značku @" a "Jméno má malý počet znaků".

Výše uvedenou podmínku lze získat pomocí následujícího SQL. Používáme však poddotazy a nekontrolovali jsme výkon.

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

Duplicitní řádky jsou having kontrolovány pomocí a count . group by Klíčový sloupec, který má být zkontrolován zvenčí, zde ID je where sloupec zúžen o .

Pořadí priorit pro načtení prvního řádku je order by určeno pomocí . charindex Zde a len zkontrolujte, zda obsahuje zadaný znak a délku řetězce. top Vše, co musíte udělat, je získat první řádek každého duplicitního záznamu v .

Původně je to v pořádku, ale pokud existují dva nebo více záznamů s přesně stejnou hodnotou, například "ID: 4, Název: Jméno 4@example.com", nevyhnutelně dostanete dva záznamy. row_number Proto je připojen tak, aby mohl být identifikován pro každý řádek pomocí , takže lze získat pouze jeden záznam s přesně stejnou hodnotou. Pokud je známo, že přesně stejný záznam neexistuje, myslím, row_number že by bylo lepší zkontrolovat hodnoty existujících záznamů bez připojování .

Pokud existuje více klíčů, které je třeba zkontrolovat z hlediska duplicit, můžete zvýšit počet sloupců klíče pro každý z nich. Představte si například následující záznam: Sloupce, které mají být zkontrolovány na duplicity, jsou "ID1" a "ID2".

ID1 ID2 Název
1 1 Název 1
2 1 Název 2
3 1 Název 31
3 2 Jméno 32
4 1 Název41
4 2 Jméno42
4 2 Jméno 4@example.com
5 1 Název 555@example.com
5 1 Název 55@example.com
5 2 Název 5@example.com
6 1 Jméno 6
6 1 Název 66@example.com
6 2 Jméno 6
6 2 Jméno 6

Výsledek akvizice je následující.

ID1 ID2 Název
4 2 Jméno 4@example.com
5 1 Název 55@example.com
6 1 Název 66@example.com
6 2 Jméno 6

SQL vypadá takto: Můžete jednoduše zvětšit část, ve které byl zadán klíčový sloupec.

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