Extrahieren Sie nur die erste Spalte aus der Datensatzeinheit, in der der Wert der angegebenen Spalte dupliziert wird
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)
)