Como selecionar todas as linhas em que o valor da coluna NÃO é distinto

154

Preciso executar uma instrução select que retorne todas as linhas em que o valor de uma coluna não é distinto (por exemplo, EmailAddress).

Por exemplo, se a tabela se parecer abaixo:

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

Eu preciso da consulta para retornar:

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

Eu li muitos posts e tentei consultas diferentes sem sucesso. A consulta que acredito que deve funcionar está abaixo. Alguém pode sugerir uma alternativa ou me dizer o que pode estar errado com minha consulta?

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

Respostas:

263

Isso é significativamente mais rápido do que o EXISTScaminho:

SELECT [EmailAddress], [CustomerName] FROM [Customers] WHERE [EmailAddress] IN
  (SELECT [EmailAddress] FROM [Customers] GROUP BY [EmailAddress] HAVING COUNT(*) > 1)
Serj Sagan
fonte
1
Ei, eu sei que essa resposta tem 7 anos, mas se você ainda estiver por perto, se importaria de explicar como ela funciona? Resolvi meu problema também!
22419 Lou Lou
4
Usar um HAVINGaqui em vez de um segundo SELECT...WHEREfaz com que seja uma consulta única, em vez da segunda opção que executa essa segunda SELECT...WHEREchamada várias vezes. Veja mais aqui: stackoverflow.com/q/9253244/550975
Serj Sagan
Eu recebo o [EmailAddress] must appear in the GROUP BY clause or be used in an aggregate functionerro infame . A única correção - editar o sql_mode?
Volodymyr Bobyr 16/07
[EmailAddress]ESTÁ na GROUP BYcláusula
Serj Sagan
51

O que está incorreto com sua consulta é que você está agrupando por email e nome, que forma um grupo de cada conjunto exclusivo de email e nome combinados e, portanto,

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

são tratados como três grupos diferentes, todos pertencendo a um único grupo.

Por favor, use a consulta como abaixo:

select emailaddress,customername from customers where emailaddress in
(select emailaddress from customers group by emailaddress having count(*) > 1)
Temperado
fonte
21
Gosto que você também tenha incluído uma explicação sobre o que está errado com a consulta original, diferente da resposta aceita.
12

E se

SELECT EmailAddress, CustomerName FROM Customers a
WHERE Exists ( SELECT emailAddress FROM customers c WHERE a.customerName != c.customerName AND a.EmailAddress = c.EmailAddress)
Marc
fonte
11
select CustomerName,count(1) from Customers group by CustomerName having count(1) > 1
Nisar
fonte
aprimoramento menor para mostrar a contagem como "dups": selecione CustomerName, count (1) como dups do grupo Customers por CustomerName com count (1)> 1`
DynamicDan
8

Apenas por diversão, aqui está outra maneira:

;with counts as (
    select CustomerName, EmailAddress,
      count(*) over (partition by EmailAddress) as num
    from Customers
)
select CustomerName, EmailAddress
from counts
where num > 1
Chade
fonte
1
+1 na versão CTE Não devemos nos repetir no código, por que nos repetir no SQL se não precisamos mais.
yzorg 17/08/16
1
Eu uso _count para a coluna count (over num). Uso consistentemente o sublinhado quando as colunas colidem com as palavras-chave SQL, como _default, _type, _sum, etc.
yzorg
4

Em vez de usar subconsultas em condições em que aumentará o tempo de consulta em que os registros são enormes.

Sugiro usar o Inner Join como uma opção melhor para esse problema.

Considerando a mesma tabela, isso poderia dar o resultado

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

Para obter resultados ainda melhores, sugiro que você use CustomerIDou qualquer campo exclusivo da sua tabela. A duplicação de CustomerNameé possível.

Naveen Kishan
fonte
-2

Bem, há uma pequena alteração para encontrar as linhas não distintas ..

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