Poimi vain ensimmäinen tietueyksiköstä, jossa määritetyn sarakkeen arvo on monistettu

Sivu päivitetty :
Sivun luontipäivämäärä :

Normaalisti, kun poimit vain yhden päällekkäisen tietueen, ensimmäinen asia, joka tulee mieleen, on distinct : distinct Ei salli sinun määrittää sarakkeen kaksoiskappaletta ja toista saraketta, jonka haluat noutaa samanaikaisesti. Lisäksidistinct ei vastaa tätä vaatimusta, koska se sisältää poiminnassa tietueita, jotka eivät ole päällekkäisiä.

En usko, että ymmärrät, mitä haluat tehdä pelkällä otsikolla, joten käytetään esimerkkitietuetta esimerkkinä. Haluan tehdä seuraavan uuttotuloksen.

Tunnuksen nimi
1 Nimi 1
2 Nimi 2
3 Nimi 3
3 Nimi 3@example.com
4 Nimi 4 Nimi 4@example.com
4 Nimi 4@example.com
4 Nimi 4@example.com

Hanki se seuraavasti:

Tunnuksen nimi
3 Nimi 3@example.com
4 Nimi 4@example.com

Tunnukset 1 ja 2 eivät sisälly, koska ne eivät ole kaksoiskappaleita. Tunnukset 3 ja 4 ovat kaksoiskappaleita, joten yksi niistä noudetaan. Tällä kertaa emme kuitenkaan saa ensimmäistä tietuetta DB-tallennustilaukseen. Oletetaan lisäksi, että haluat nimen ensimmäisen rivin tärkeysjärjestyksessä ehdoilla, että "Nimi sisältää @-merkin" ja "Nimessä on pieni määrä merkkejä".

Yllä oleva ehto voidaan saada seuraavalla SQL:llä. Käytämme kuitenkin alikyselyitä, emmekä ole tarkistaneet suorituskykyä.

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

Rivien kaksoiskappaleet tarkistetaan having komennoilla ja . count group by Ulkopuolelta tarkistettava avainsarake, tässä ID sarake on kavennettu where .

Ensimmäisen rivin noutamisen tärkeysjärjestys on order by määritetty . charindex Tässä ja len tarkista, sisältääkö se määritetyn merkin ja merkkijonon pituuden. top Sinun tarvitsee vain saada kunkin tietueen kaksoiskappaleen ensimmäinen rivi .

Alun perin tämä on hyvä, mutta jos on kaksi tai useampia tietueita, joilla on täsmälleen sama arvo, kuten "ID: 4, Name: Name 4@example.com", saat väistämättä kaksi tietuetta. row_number Siksi se liitetään siten, että se voidaan tunnistaa kullekin riville merkillä , jotta vain yksi tietue, jolla on täsmälleen sama arvo, voidaan noutaa. Jos tiedetään, että täsmälleen samaa tietuetta ei ole olemassa, row_number mielestäni olisi parempi tarkistaa olemassa olevien tietueiden arvot liittämättä .

Jos kaksoiskappaleiden varalta tarkistetaan useita avaimia, voit lisätä avainsarakkeiden määrää kullekin avaimelle. Tarkastellaan esimerkiksi seuraavaa tietuetta: Kaksoiskappaleiden varalta tarkistettavat sarakkeet ovat "ID1" ja "ID2".

ID1ID2-nimi
1 1 Nimi 1
2 1 Nimi 2
3 1 Nimi 31
3 2 Nimi 32
4 1 Nimi41
4 2 Nimi42
4 2 Nimi 4@example.com
5 1 Nimi 555@example.com
5 1 Nimi 55@example.com
5 2 Nimi 5@example.com
6 1 Nimi 6
6 1 Nimi 66@example.com
6 2 Nimi 6
6 2 Nimi 6

Yritysoston tulos on seuraava.

ID1ID2-nimi
4 2 Nimi 4@example.com
5 1 Nimi 55@example.com
6 1 Nimi 66@example.com
6 2 Nimi 6

SQL näyttää tältä: Voit yksinkertaisesti suurentaa osaa, jossa avainsarake on määritetty.

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