Extraheer alleen de eerste uit de recordeenheid waar de waarde van de opgegeven kolom wordt gedupliceerd
Normaal gesproken, bij het extraheren van slechts één duplicaat record, is distinct
het eerste dat in me opkomt dat ik denk:
distinct
Hiermee kunt u niet tegelijkertijd een dubbele kolom en een andere kolom opgeven die u wilt ophalen.
Bovendiendistinct
voldoet het niet aan deze vereiste omdat het niet-dubbele records in de extractie opneemt.
Ik denk niet dat je kunt begrijpen wat je met de titel alleen wilt doen, dus laten we een voorbeeldplaat als voorbeeld nemen. Wat ik wil doen is het volgende extractieresultaat.
ID | Naam |
---|---|
1 | Naam 1 |
2 | Naam 2 |
3 | Naam 3 |
3 | Naam 3@example.com |
4 | Naam 4 Naam 4@example.com |
4 | Naam 4@example.com |
4 | Naam 4@example.com |
Krijg het als volgt:
ID | Naam |
---|---|
3 | Naam 3@example.com |
4 | Naam 4@example.com |
ID's 1 en 2 zijn niet opgenomen omdat het geen duplicaten zijn. ID's 3 en 4 zijn duplicaten, dus een ervan wordt opgehaald. Deze keer krijgen we echter niet de eerste record in de DB-opslagorder. Stel daarnaast dat u de eerste regel van de naam in volgorde van prioriteit wilt hebben onder de voorwaarden dat "Naam bevat een @-teken" en "Naam heeft een klein aantal tekens".
Bovenstaande voorwaarde kan worden verkregen met de volgende SQL. We maken echter gebruik van subquery's en hebben de prestaties niet gecontroleerd.
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)
)
Dubbele rijen worden having
aangevinkt met en count
. group by
De belangrijkste kolom die van buitenaf moet worden gecontroleerd, hier ID
wordt where
de kolom versmald door .
De volgorde van prioriteit voor het ophalen van de eerste rij wordt order by
aangegeven door . charindex
Hier, en len
controleer of het het opgegeven teken en de lengte van de tekenreeks bevat.
top
Het enige dat u hoeft te doen, is de eerste rij van elk dubbel record in .
Oorspronkelijk is dit prima, maar als er twee of meer records zijn met exact dezelfde waarde, zoals "ID: 4, Name: Name 4@example.com", krijg je onvermijdelijk twee records.
row_number
Daarom wordt het toegevoegd zodat het voor elke rij kan worden geïdentificeerd met , zodat slechts één record met exact dezelfde waarde kan worden opgehaald.
Als bekend is dat exact hetzelfde record niet bestaat, denk ik row_number
dat het beter is om de waarden van de bestaande records te controleren zonder toe te voegen.
Als er meerdere sleutels zijn die op duplicaten moeten worden gecontroleerd, kunt u het aantal sleutelkolommen voor elke sleutel verhogen. Neem bijvoorbeeld de volgende record: De kolommen die op duplicaten moeten worden gecontroleerd, zijn "ID1" en "ID2".
ID1 | ID2 | Naam |
---|---|---|
1 | 1 | Naam 1 |
2 | 1 | Naam 2 |
3 | 1 | Naam 31 |
3 | 2 | Naam 32 |
4 | 1 | Naam41 |
4 | 2 | Naam42 |
4 | 2 | Naam 4@example.com |
5 | 1 | Naam 555@example.com |
5 | 1 | Naam 55@example.com |
5 | 2 | Naam 5@example.com |
6 | 1 | Naam 6 |
6 | 1 | Naam 66@example.com |
6 | 2 | Naam 6 |
6 | 2 | Naam 6 |
Het overnameresultaat is als volgt.
ID1 | ID2 | Naam |
---|---|---|
4 | 2 | Naam 4@example.com |
5 | 1 | Naam 55@example.com |
6 | 1 | Naam 66@example.com |
6 | 2 | Naam 6 |
De SQL ziet er als volgt uit: U kunt eenvoudig het gedeelte vergroten waar de sleutelkolom is opgegeven.
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)
)