Cómo seleccionar cada fila donde el valor de la columna NO es distinto

154

Necesito ejecutar una instrucción select que devuelva todas las filas donde el valor de una columna no es distinto (por ejemplo, EmailAddress).

Por ejemplo, si la tabla se ve a continuación:

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

Necesito que la consulta regrese:

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

He leído muchas publicaciones y he intentado diferentes consultas en vano. La consulta que creo que debería funcionar está a continuación. ¿Alguien puede sugerir una alternativa o decirme qué puede estar mal con mi consulta?

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

Respuestas:

263

Esto es significativamente más rápido que la EXISTSforma:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)
Serj Sagan
fuente
1
Oye, sé que esta respuesta tiene 7 años, pero si todavía estás cerca, ¿te importaría explicar cómo funciona? ¡También resolvió mi problema!
Lou
44
El uso de un HAVINGaquí en lugar de un segundo SELECT...WHEREhace que se trate de una sola consulta, en lugar de la segunda opción que ejecuta esa segunda SELECT...WHEREllamada muchas veces. Ver más aquí: stackoverflow.com/q/9253244/550975
Serj Sagan
Me sale el infame [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionerror. ¿Es la única solución: editar el sql_mode?
Volodymyr Bobyr
[EmailAddress]IS en la GROUP BYcláusula
Serj Sagan
51

Lo incorrecto con su consulta es que está agrupando por correo electrónico y nombre, que forma un grupo de cada conjunto único de correo electrónico y nombre combinados y, por lo tanto,

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

se tratan como 3 grupos diferentes en lugar de pertenecer a un solo grupo.

Utilice la consulta como se indica a continuación:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)
Sazonado
fuente
21
Me gusta que también haya incluido una explicación sobre lo que está mal en la consulta original, a diferencia de la respuesta aceptada.
12

Qué tal si

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)
Bagazo
fuente
11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1
Nisar
fuente
Mejora menor para mostrar el conteo como "dups": seleccione CustomerName, count (1) como dups del grupo Clientes por CustomerName teniendo count (1)> 1`
DynamicDan
8

Solo por diversión, aquí hay otra forma:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1
Chad
fuente
1
+1 para la versión CTE No deberíamos repetirnos en código, ¿por qué repetirnos en SQL si ya no tenemos que hacerlo?
yzorg
1
Yo uso _count para la columna de conteo (sobre num). Siempre uso guiones bajos cuando las columnas chocan con palabras clave SQL como _default, _type, _sum, etc.
yzorg
4

En lugar de usar subconsultas en la condición where, lo que aumentará el tiempo de consulta donde los registros son enormes.

Sugeriría usar Inner Join como una mejor opción para este problema.

Considerando la misma tabla esto podría dar el resultado

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

Para obtener resultados aún mejores, le sugiero que utilice CustomerIDo cualquier campo único de su tabla. La duplicación de CustomerNamees posible.

Naveen Kishan
fuente
-2

Bueno, hay un ligero cambio para encontrar las filas no distintas ...

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