Extrahujte pouze první z jednotek záznamu, ve kterém je hodnota zadaného sloupce duplikována
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)
)