Comment sélectionner chaque ligne où la valeur de la colonne n'est PAS distincte

154

J'ai besoin d'exécuter une instruction de sélection qui renvoie toutes les lignes où la valeur d'une colonne n'est pas distincte (par exemple EmailAddress).

Par exemple, si le tableau ressemble à ci-dessous:

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

J'ai besoin de la requête pour retourner:

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

J'ai lu de nombreux articles et essayé différentes requêtes en vain. La requête qui, selon moi, devrait fonctionner est ci-dessous. Quelqu'un peut-il suggérer une alternative ou me dire ce qui ne va pas avec ma requête?

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

Réponses:

263

C'est nettement plus rapide que la EXISTSmanière:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)
Serj Sagan
la source
1
Hé, je sais que cette réponse a 7 ans, mais si vous êtes toujours là, cela vous dérangerait d'expliquer comment cela fonctionne? J'ai également résolu mon problème!
Lou
4
L'utilisation d'un HAVINGici au lieu d'une seconde SELECT...WHEREfait qu'il s'agit d'une seule requête, au lieu de la seconde option qui exécute ce second SELECT...WHEREappel plusieurs fois. Voir plus ici: stackoverflow.com/q/9253244/550975
Serj Sagan
Je reçois la tristement célèbre [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionerreur. Est le seul correctif - modifier le sql_mode?
Volodymyr Bobyr le
[EmailAddress]EST dans la GROUP BYclause
Serj Sagan le
51

Ce qui est incorrect avec votre requête, c'est que vous groupez par e-mail et par nom, qui forme un groupe de chaque ensemble unique d'e-mail et de nom combinés ensemble et donc

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

sont traités comme 3 groupes différents plutôt que tous appartenant à un seul groupe.

Veuillez utiliser la requête ci-dessous:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)
Chevronné
la source
21
J'aime que vous ayez également inclus une explication sur ce qui ne va pas avec la requête d'origine, contrairement à la réponse acceptée.
12

Que diriez-vous

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)
Marc
la source
11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1
Nisar
la source
amélioration mineure pour afficher le nombre comme "dups": sélectionnez CustomerName, comptez (1) comme dups du groupe de clients par CustomerName ayant le nombre (1)> 1`
DynamicDan
8

Juste pour le plaisir, voici une autre façon:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1
Tchad
la source
1
+1 pour la version CTE Nous ne devrions pas nous répéter dans le code, pourquoi nous répéter en SQL si nous n'en avons plus besoin.
yzorg
1
J'utilise _count pour la colonne count (sur num). J'utilise systématiquement un trait de soulignement lorsque des colonnes entrent en collision avec des mots-clés SQL tels que _default, _type, _sum, etc.
yzorg
4

Plutôt que d'utiliser des sous-requêtes dans la condition where qui augmentera le temps de requête lorsque les enregistrements sont énormes.

Je suggérerais d'utiliser Inner Join comme une meilleure option à ce problème.

Considérant le même tableau cela pourrait donner le résultat

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

Pour des résultats encore meilleurs, je vous suggère d'utiliser CustomerIDou n'importe quel champ unique de votre table. La duplication de CustomerNameest possible.

Naveen Kishan
la source
-2

Eh bien, il y a un léger changement pour trouver les lignes non distinctes.

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