2 Stimmen

TSQL Group By mit einem "OR"?

Diese Abfrage zur Erstellung einer Liste von Kandidaten-Duplikaten ist einfach genug:

SELECT Count(*), Can_FName, Can_HPhone, Can_EMail
FROM Can 
GROUP BY Can_FName, Can_HPhone, Can_EMail
HAVING Count(*) > 1

Aber wenn die eigentliche Regel, die ich überprüfen möchte, FName und (HPhone OR Email) ist - wie kann ich die GROUP BY anpassen, um mit diesem zu arbeiten?

Ich bin ziemlich sicher, ich werde am Ende mit einem UNION SELECT hier (d.h. tun FName, HPhone auf eine und FName, EMail auf die andere und kombinieren die Ergebnisse) - aber ich würde gerne wissen, wenn jemand einen einfacheren Weg, es zu tun kennt.

Ich danke Ihnen im Voraus für jede Hilfe.

Scott in Maine

0 Stimmen

Sie wollen also, dass 'Bob / 567 / irgendwas', 'Bob / irgendwas / bob@bob.com' und 'Bob / 567 / bob@bob.com' als Duplikate gezählt werden? Was ist, wenn es einen "Bob / 234 / bob@bob.com" gibt? Einige Datenbeispiele zur Verdeutlichung Ihrer Gruppierungsregel wären sehr hilfreich.

0 Stimmen

Nachvollziehbar. Das tut mir leid. Quassnoi hat unten ein gutes Beispiel gegeben (und ich habe die Frage dort beantwortet). Ich danke Ihnen.

0 Stimmen

Möchten Sie tatsächlich Duplikate entfernen?

0voto

msi77 Punkte 1522

Versuchen Sie dies:

SELECT Can_FName, COUNT(*)
FROM (
SELECT 
rank() over(partition by Can_FName order by  Can_FName,Can_HPhone) rnk_p,
rank() over(partition by Can_FName order by  Can_FName,Can_EMail) rnk_m,
Can_FName
FROM Can
) X
WHERE rnk_p=1 or rnk_m =1
GROUP BY Can_FName
HAVING COUNT(*)>1

0voto

Michael Petter Punkte 96

Keine dieser Antworten ist richtig. Der Ansatz von Quassnoi ist anständig, aber Sie werden einen fatalen Fehler in den Ausdrücken "qo.id > dup.id" und "di.chainid < do.chainid" bemerken: Vergleiche nach ID! Dies ist IMMER eine schlechte Praxis, weil sie von einer inhärenten Ordnung in den IDs abhängt. IDs sollten NIEMALS eine implizite Bedeutung erhalten und sollten NUR an Gleichheits- oder Nulltests teilnehmen. Sie können die Lösung von Quassnoi in diesem Beispiel leicht umgehen, indem Sie einfach die IDs in den Daten neu anordnen.

Das Hauptproblem ist eine disjunkte Bedingung mit einer Gruppierung, die dazu führt, dass zwei Datensätze durch ein Zwischenprodukt miteinander verbunden sein können, obwohl sie nicht direkt miteinander verbunden sind.

Sie haben z. B. angegeben, dass diese Datensätze alle gruppiert werden sollen:

(1) John 555-00-00 john@example.com

(2) John 555-00-01 john@example.com

(3) John 555-00-01 john-other@example.com

Sie können sehen, dass #1 und #2 beziehbar sind, ebenso wie #2 und #3, aber eindeutig sind #1 und #3 als Gruppe nicht direkt beziehbar.

Daraus ergibt sich, dass eine rekursive oder iterative Lösung die einzig mögliche Lösung ist.

Eine Rekursion ist also nicht praktikabel, da man leicht in eine Schleife geraten kann. Genau das wollte Quassnoi mit seinen ID-Vergleichen vermeiden, aber dabei hat er den Algorithmus zerstört. Man könnte versuchen, die Rekursionsebenen einzuschränken, aber dann werden möglicherweise nicht alle Beziehungen abgeschlossen, und man wird möglicherweise immer noch Schleifen auf sich selbst zurückführen, was zu einer übermäßigen Datengröße und untragbarer Ineffizienz führt.

Die beste Lösung ist ITERATIV: Starten Sie eine Ergebnismenge, indem Sie jede ID als eindeutige Gruppen-ID markieren, und aktualisieren Sie dann die Ergebnismenge, indem Sie die IDs zu derselben eindeutigen Gruppen-ID kombinieren, wenn sie mit der disjunkten Bedingung übereinstimmen. Wiederholen Sie den Vorgang an der aktualisierten Menge jedes Mal, bis keine weiteren Aktualisierungen mehr möglich sind.

Ich werde demnächst einen Beispielcode für diese Funktion erstellen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X