Jak wybrać każdy wiersz, w którym wartość kolumny NIE jest odrębna

154

Muszę uruchomić instrukcję Select, która zwraca wszystkie wiersze, w których wartość kolumny nie jest odrębna (np. EmailAddress).

Na przykład, jeśli tabela wygląda jak poniżej:

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

Potrzebuję zapytania do zwrotu:

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

Przeczytałem wiele postów i bezskutecznie próbowałem różnych zapytań. Zapytanie, które moim zdaniem powinno zadziałać, znajduje się poniżej. Czy ktoś może zasugerować alternatywę lub powiedzieć mi, co może być nie tak z moim zapytaniem?

select EmailAddress, CustomerName from Customers
group by EmailAddress, CustomerName
having COUNT(distinct(EmailAddress)) > 1
Konik polny
źródło

Odpowiedzi:

263

Jest to znacznie szybsze niż EXISTSsposób:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)
Serj Sagan
źródło
1
Hej, wiem, że ta odpowiedź ma 7 lat, ale jeśli nadal jesteś w pobliżu, czy możesz wyjaśnić, jak to działa? Rozwiązał również mój problem!
Lou
4
Użycie HAVINGtu zamiast sekundy SELECT...WHEREpowoduje, że jest to pojedyncze zapytanie zamiast drugiej opcji, która SELECT...WHEREwielokrotnie wykonuje to drugie wywołanie. Zobacz więcej tutaj: stackoverflow.com/q/9253244/550975
Serj Sagan,
Otrzymuję niesławny [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionbłąd. Czy jedyną poprawką jest edycja pliku sql_mode?
Volodymyr Bobyr
[EmailAddress]JEST w GROUP BYklauzuli
Serj Sagan
51

Niepoprawne w zapytaniu jest to, że grupujesz według adresu e-mail i imienia i nazwiska, które tworzą grupę każdego unikalnego zestawu adresów e-mail i nazwy połączonych razem, a zatem

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

są traktowane jako 3 różne grupy, a wszystkie należące do jednej grupy.

Użyj zapytania, jak podano poniżej:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)
Zaprawiony
źródło
21
Podoba mi się, że dołączyłeś również wyjaśnienie, co jest nie tak w pierwotnym zapytaniu, w przeciwieństwie do zaakceptowanej odpowiedzi.
12

Co powiesz na

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)
Marc
źródło
11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1
Nisar
źródło
niewielkie ulepszenie pokazujące licznik jako „dups”: wybierz CustomerName, count (1) as dups z grupy Customers by CustomerName mając count (1)> 1`
DynamicDan
8

Dla zabawy, oto inny sposób:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1
Czad
źródło
1
+1 dla wersji CTE Nie powinniśmy powtarzać się w kodzie, po co powtarzać się w SQL, jeśli już nie musimy.
yzorg,
1
Używam _count dla kolumny zliczania (ponad num). Konsekwentnie używam podkreślenia, gdy kolumny kolidują ze słowami kluczowymi SQL, takimi jak _default, _type, _sum itp.
yzorg
4

Zamiast używać zapytań podrzędnych w przypadku, gdy warunek wydłuży czas zapytania, gdy rekordy są ogromne.

Sugerowałbym użycie połączenia wewnętrznego jako lepszej opcji rozwiązania tego problemu.

Biorąc pod uwagę tę samą tabelę, może to dać wynik

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

Aby uzyskać jeszcze lepsze wyniki, sugerowałbym użycie CustomerIDdowolnego unikalnego pola tabeli. CustomerNameMożliwe jest powielanie .

Naveen Kishan
źródło
-2

Cóż, istnieje niewielka zmiana, aby znaleźć nierozróżnialne wiersze.

SELECT EmailAddress, CustomerName FROM Customers WHERE EmailAddress NOT IN
(SELECT EmailAddress FROM Customers GROUP BY EmailAddress HAVING COUNT(*) > 1)
Rashmi Ranjan Ransingh
źródło