So wählen Sie jede Zeile aus, in der der Spaltenwert NICHT eindeutig ist

154

Ich muss eine select-Anweisung ausführen, die alle Zeilen zurückgibt, in denen der Wert einer Spalte nicht eindeutig ist (z. B. EmailAddress).

Zum Beispiel, wenn die Tabelle wie folgt aussieht:

CustomerName     EmailAddress
Aaron            aaron@gmail.com
Christy          aaron@gmail.com
Jason            jason@gmail.com
Eric             eric@gmail.com
John             aaron@gmail.com

Ich brauche die Abfrage, um zurückzukehren:

Aaron            aaron@gmail.com
Christy          aaron@gmail.com
John             aaron@gmail.com

Ich habe viele Beiträge gelesen und verschiedene Fragen ohne Erfolg ausprobiert. Die Abfrage, von der ich glaube, dass sie funktionieren sollte, ist unten. Kann mir jemand eine Alternative vorschlagen oder mir sagen, was mit meiner Anfrage falsch sein könnte?

select EmailAddress, CustomerName from Customers
group by EmailAddress, CustomerName
having COUNT(distinct(EmailAddress)) > 1
Heuschrecke
quelle

Antworten:

263

Dies ist deutlich schneller als der EXISTSWeg:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)
Serj Sagan
quelle
1
Hey, ich weiß, dass diese Antwort 7 Jahre alt ist, aber wenn Sie noch da sind, würde es Ihnen etwas ausmachen zu erklären, wie es funktioniert? Mein Problem wurde auch gelöst!
Lou
4
Wenn Sie HAVINGhier statt einer Sekunde verwenden, SELECT...WHEREhandelt es sich um eine einzelne Abfrage anstelle der zweiten Option, die diesen zweiten SELECT...WHEREAufruf viele Male ausführt . Weitere Informationen finden Sie
Serj Sagan
Ich bekomme den berüchtigten [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionFehler. Ist das einzige Update - das Bearbeiten sql_mode?
Volodymyr Bobyr
[EmailAddress]IS in der GROUP BYKlausel
Serj Sagan
51

Was bei Ihrer Abfrage falsch ist, ist, dass Sie nach E-Mail und Namen gruppieren, die eine Gruppe jedes einzelnen Satzes von E-Mail und Namen bilden, die zusammen und somit kombiniert werden

aaron and aaron@gmail.com
christy and aaron@gmail.com
john and aaron@gmail.com

werden als 3 verschiedene Gruppen behandelt, die alle zu einer einzigen Gruppe gehören.

Bitte verwenden Sie die unten angegebene Abfrage:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)
Gewürzt
quelle
21
Ich finde es gut, dass Sie im Gegensatz zur akzeptierten Antwort auch eine Erklärung hinzugefügt haben, was mit der ursprünglichen Abfrage nicht stimmt.
12

Wie wäre es mit

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)
Marc
quelle
11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1
Nisar
quelle
geringfügige Verbesserung, um die Anzahl als "Dups" anzuzeigen: Wählen Sie "Kundenname", "Anzahl (1)" als "Dups" aus der Kundengruppe nach "Kundenname" mit "Anzahl (1)> 1"
DynamicDan
8

Nur zum Spaß, hier ist ein anderer Weg:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1
Tschad
quelle
1
+1 für CTE-Version Wir sollten uns nicht im Code wiederholen, warum sollten wir uns in SQL wiederholen, wenn wir nicht mehr müssen.
Yzorg
1
Ich benutze _count für die Zählspalte (über num). Ich verwende konsequent Unterstriche, wenn Spalten zufällig mit SQL-Schlüsselwörtern wie _default, _type, _sum usw.
kollidieren
4

Anstatt Unterabfragen in einem Where-Zustand zu verwenden, erhöht sich die Abfragezeit bei großen Datensätzen.

Ich würde vorschlagen, Inner Join als bessere Option für dieses Problem zu verwenden.

In Anbetracht derselben Tabelle könnte dies das Ergebnis ergeben

SELECT EmailAddress, CustomerName FROM Customers as a 
Inner Join Customers as b on a.CustomerName <> b.CustomerName and a.EmailAddress = b.EmailAddress

Für noch bessere Ergebnisse würde ich Ihnen empfehlen, ein CustomerIDbeliebiges Feld Ihrer Tabelle zu verwenden. Eine Vervielfältigung von CustomerNameist möglich.

Naveen Kishan
quelle
-2

Nun, es gibt eine kleine Änderung, um die nicht unterschiedlichen Zeilen zu finden.

SELECT EmailAddress, CustomerName FROM Customers WHERE EmailAddress NOT IN
(SELECT EmailAddress FROM Customers GROUP BY EmailAddress HAVING COUNT(*) > 1)
Rashmi Ranjan Ransingh
quelle