Wyodrębnij tylko pierwszą z jednostki rekordu, w której jest zduplikowana wartość określonej kolumny

Strona zaktualizowana :
Data utworzenia strony :

Zwykle, gdy wyodrębniasz tylko jeden zduplikowany rekord, pierwszą rzeczą, która przychodzi na myśl, jest distinct to, że distinct Nie pozwala na określenie zduplikowanej kolumny i innej kolumny, które mają zostać pobrane w tym samym czasie. Ponadto nie spełnia tego wymagania,distinct ponieważ zawiera niezduplikowane rekordy w wyodrębnianiu.

Nie sądzę, żebyś mógł zrozumieć, co chcesz zrobić z samym tytułem, więc użyjmy przykładowego rekordu jako przykładu. To, co chcę zrobić, to następujący wynik ekstrakcji.

tożsamości
Nazwa dowodu
1 Imię 1
2 Imię 2
3 Imię 3
3 Imię i nazwisko 3@example.com
4 Imię 4 Imię 4@example.com
4 Imię i nazwisko 4@example.com
4 Imię i nazwisko 4@example.com

Zdobądź go w następujący sposób:

tożsamości
Nazwa dowodu
3 Imię i nazwisko 3@example.com
4 Imię i nazwisko 4@example.com

Identyfikatory 1 i 2 nie są uwzględniane, ponieważ nie są duplikatami. Identyfikatory 3 i 4 są duplikatami, więc jeden z nich jest pobierany. Tym razem jednak nie otrzymamy pierwszego rekordu w kolejności przechowywania bazy danych. Ponadto załóżmy, że pierwszy wiersz nazwy ma być ułożony w kolejności priorytetu w warunkach, że "Nazwa zawiera znak @" i "Nazwa ma niewielką liczbę znaków".

Powyższy warunek można uzyskać za pomocą następującego kodu SQL. Używamy jednak podzapytań i nie sprawdziliśmy wydajności.

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

Zduplikowane wiersze są having sprawdzane za pomocą i count . group by Kluczowa kolumna, która ma być sprawdzana z zewnątrz, tutaj ID kolumna jest where zawężona przez .

Kolejność pierwszeństwa pobierania pierwszego wiersza jest order by określona przez . charindex Tutaj i len sprawdź, czy zawiera określony znak i długość ciągu. top Wszystko, co musisz zrobić, to uzyskać pierwszy wiersz każdego zduplikowanego rekordu w .

Początkowo jest to w porządku, ale jeśli istnieją dwa lub więcej rekordów o dokładnie tej samej wartości, takich jak "ID: 4, Nazwa: Nazwa 4@example.com", nieuchronnie otrzymasz dwa rekordy. row_number W związku z tym jest dołączany tak, aby można go było zidentyfikować dla każdego wiersza za pomocą , dzięki czemu można pobrać tylko jeden rekord o dokładnie tej samej wartości. Jeśli wiadomo, że dokładnie ten sam rekord nie istnieje, myślę, row_number że lepiej byłoby sprawdzić wartości istniejących rekordów bez dołączania .

Jeśli istnieje wiele kluczy, które mają zostać sprawdzone pod kątem duplikatów, można zwiększyć liczbę kolumn kluczy dla każdego z nich. Rozważmy na przykład następujący rekord: Kolumny, które mają zostać sprawdzone pod kątem duplikatów, to 'ID1' i 'ID2'.

ID1 ID2 Nazwa
1 1 Imię 1
2 1 Imię 2
3 1 Imię 31
3 2 Imię 32
4 1 Nazwa41 powiedział:
4 2 Nazwa42 powiedział:
4 2 Imię i nazwisko 4@example.com
5 1 Imię 555@example.com
5 1 Imię 55@example.com
5 2 Imię i nazwisko 5@example.com
6 1 Imię 6
6 1 Imię i nazwisko 66@example.com
6 2 Imię 6
6 2 Imię 6

Wynik przejęcia przedstawia się następująco.

ID1 ID2 Nazwa
4 2 Imię i nazwisko 4@example.com
5 1 Imię 55@example.com
6 1 Imię i nazwisko 66@example.com
6 2 Imię 6

SQL wygląda tak: Możesz po prostu zwiększyć część, w której została określona kolumna klucza.

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