Extrahieren Sie nur die erste Spalte aus der Datensatzeinheit, in der der Wert der angegebenen Spalte dupliziert wird

Diese Seite wurde aktualisiert :
Erstellungsdatum der Seite :

Normalerweise, wenn ich nur einen doppelten Datensatz extrahiere, ist das erste, was mir distinct in den Sinn kommt, denke ich: distinct Ermöglicht es Ihnen nicht, eine doppelte Spalte und eine andere Spalte anzugeben, die Sie gleichzeitig abrufen möchten. Darüber hinausdistinct entspricht es dieser Anforderung nicht, da es nicht doppelte Datensätze in die Extraktion einschließt.

Ich glaube nicht, dass Sie allein mit dem Titel verstehen können, was Sie damit anfangen wollen, also nehmen wir eine Beispielplatte als Beispiel. Was ich tun möchte, ist das folgende Extraktionsergebnis.

ID-Name
1 Name 1
2 Name 2
3 Name 3
3 Name 3@example.com
4 Name 4 Name 4@example.com
4 Name 4@example.com
4 Name 4@example.com

Holen Sie es sich wie folgt:

ID-Name
3 Name 3@example.com
4 Name 4@example.com

Die IDs 1 und 2 sind nicht enthalten, da es sich nicht um Duplikate handelt. Die IDs 3 und 4 sind Duplikate, daher wird eine von ihnen abgerufen. Dieses Mal erhalten wir jedoch nicht den ersten Datensatz in der DB-Speicherreihenfolge. Nehmen Sie außerdem an, dass Sie die erste Zeile des Namens in der Reihenfolge ihrer Priorität unter den Bedingungen "Name enthält ein @-Zeichen" und "Name hat eine kleine Anzahl von Zeichen" haben möchten.

Die obige Bedingung kann mit dem folgenden SQL erreicht werden. Wir verwenden jedoch Unterabfragen und haben die Leistung nicht überprüft.

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

Doppelte Zeilen werden having mit und count geprüft. group by Die Schlüsselspalte, die von außen überprüft werden soll, hier ID wird where die Spalte um eingegrenzt.

Die Rangfolge für das Abrufen der ersten Zeile wird order by durch angegeben. charindex und prüfen Sie, len ob es das angegebene Zeichen und die Länge der Zeichenkette enthält. top Alles, was Sie tun müssen, ist, die erste Zeile jedes doppelten Datensatzes in abzurufen.

Ursprünglich ist das in Ordnung, aber wenn es zwei oder mehr Datensätze mit genau demselben Wert gibt, z. B. "ID: 4, Name: Name 4@example.com", erhalten Sie unweigerlich zwei Datensätze. row_number Daher wird es so angehängt, dass es für jede Zeile mit identifiziert werden kann, so dass nur ein Datensatz mit genau demselben Wert abgerufen werden kann. Wenn bekannt ist, dass genau derselbe Datensatz nicht existiert, wäre es meiner Meinung row_number nach besser, die Werte der vorhandenen Datensätze zu überprüfen, ohne anzuhängen.

Wenn es mehrere Schlüssel gibt, die auf Duplikate überprüft werden sollen, können Sie die Anzahl der Schlüsselspalten für jeden Schlüssel erhöhen. Betrachten Sie beispielsweise den folgenden Datensatz: Die Spalten, die auf Duplikate überprüft werden sollen, sind "ID1" und "ID2".

ID1 ID2 Name
1 1 Name 1
2 1 Name 2
3 1 Name 31
3 2 Name 32
4 1 Name41
4 2 Name42
4 2 Name 4@example.com
5 1 Name 555@example.com
5 1 Name 55@example.com
5 2 Name 5@example.com
6 1 Name 6
6 1 Name 66@example.com
6 2 Name 6
6 2 Name 6

Das Akquisitionsergebnis stellt sich wie folgt dar.

ID1 ID2 Name
4 2 Name 4@example.com
5 1 Name 55@example.com
6 1 Name 66@example.com
6 2 Name 6

Die SQL sieht folgendermaßen aus: Sie können einfach den Teil vergrößern, an dem die Schlüsselspalte angegeben wurde.

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