Come selezionare ogni riga in cui il valore della colonna NON è distinto


154

Devo eseguire un'istruzione select che restituisca tutte le righe in cui il valore di una colonna non è distinto (ad esempio EmailAddress).

Ad esempio, se la tabella appare come di seguito:

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

Ho bisogno della query per restituire:

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

Ho letto molti post e ho provato diverse query senza risultati. La domanda che credo dovrebbe funzionare è sotto. Qualcuno può suggerire un'alternativa o dirmi cosa potrebbe esserci di sbagliato nella mia query?

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

Risposte:


263

Questo è significativamente più veloce del EXISTSmodo:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)

1
Ehi, so che questa risposta ha 7 anni, ma se sei ancora in giro ti dispiacerebbe spiegare come funziona? Risolto anche il mio problema!
Lou

4
L'uso di un HAVINGqui invece di un secondo SELECT...WHEREfa sì che questa sia una singola query, invece della seconda opzione che esegue SELECT...WHEREpiù volte quella seconda chiamata. Vedi di più qui: stackoverflow.com/q/9253244/550975
Serj Sagan

Ottengo l' [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionerrore infame . L'unica soluzione è modificare il sql_mode?
Volodymyr Bobyr,

[EmailAddress]È nella GROUP BYclausola
Serj Sagan

51

La cosa che non è corretta con la tua query è che stai raggruppando per email e nome, che forma un gruppo di ogni set unico di email e nome combinati insieme e quindi

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

sono trattati come 3 gruppi diversi, piuttosto tutti appartenenti a 1 singolo gruppo.

Si prega di utilizzare la query come indicato di seguito:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)

21
Mi piace il fatto che tu abbia incluso anche una spiegazione di ciò che non va nella query originale, diversamente dalla risposta accettata.

12

Che ne dite di

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)

11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1

miglioramento minore per mostrare il conteggio come "duplicati": selezionare CustomerName, contare (1) come duplicati dal gruppo Clienti per CustomerName con conteggio (1)> 1`
DynamicDan

8

Solo per divertimento, ecco un altro modo:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1

1
+1 per la versione CTE Non dovremmo ripetere noi stessi nel codice, perché ripetere noi stessi in SQL se non dobbiamo più.
yzorg,

1
Uso _count per la colonna dei conteggi (oltre num). Uso costantemente il trattino basso quando le colonne si scontrano con parole chiave SQL come _default, _type, _sum, ecc.
yzorg

4

Invece di utilizzare le query secondarie in cui condizione che aumenterà il tempo di query in cui i record sono enormi.

Suggerirei di utilizzare Inner Join come migliore opzione a questo problema.

Considerando la stessa tabella questo potrebbe dare il risultato

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

Per risultati ancora migliori, ti suggerisco di utilizzare CustomerIDo qualsiasi campo unico della tua tabella. La duplicazione di CustomerNameè possibile.


-2

Bene c'è una leggera modifica per trovare le righe non distinte ..

SELECT EmailAddress, CustomerName FROM Customers WHERE EmailAddress NOT IN
(SELECT EmailAddress FROM Customers GROUP BY EmailAddress HAVING COUNT(*) > 1)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.