Selecione onde a contagem de um campo é maior que um

100

Eu quero fazer algo assim:

SELECT * 
  FROM db.table 
 WHERE COUNT(someField) > 1

Como posso fazer isso no MySql?

Stevebot
fonte

Respostas:

146

Use a cláusula HAVING, not WHERE, para comparação de resultados agregados.

Tomando a consulta pelo valor de face:

SELECT * 
  FROM db.table 
HAVING COUNT(someField) > 1

Idealmente, deve haver um GROUP BYdefinido para a avaliação adequada na HAVINGcláusula, mas o MySQL não permite colunas ocultas do GROUP BY ...

Isso está em preparação para uma restrição exclusiva someField? Parece que deveria ser ...

Pôneis OMG
fonte
11
Precisa de uma GROUP BYcerteza (a menos que seja alguma coisa não padrão do MySQL)?
Martin Smith,
@Martin Smith: Aceitou a consulta pelo valor de face; abordou o problema de GROUP BY (incluindo o recurso de colunas ocultas).
Pôneis OMG de
"Parece que deveria ser ..." Por quê? Estou precisando de informações sobre isso :)
Dave
Portanto, isso retornará a tabela inteira se ela contiver mais de 2 someFieldvalores não nulos ou um conjunto de resultados vazio se não contiver .
Martin Smith,
@Dave: Se você estivesse em uma posição em que tivesse que verificar e corrigir dados incorretos periodicamente, não gostaria de impedir que a situação acontecesse? MySQL implementa uma restrição única como um índice - para obter mais informações, consulte a documentação CREATE INDEX
Pôneis OMG
18
SELECT username, numb from(
Select username, count(username) as numb from customers GROUP BY username ) as my_table
WHERE numb > 3
dandy_sql
fonte
3
a única ressalva aqui (pelo menos em 5.1.46-community MySQL Community Server (GPL)) é que "Cada tabela derivada deve ter seu próprio alias", que fará com que seu sql se pareça com: SELECT username, numb from (Select username, contagem (nome de usuário) como numb de clientes GROUP BY nome de usuário) como minha_tabela WHERE numb> 3
D_K
14

Você também pode fazer isso com uma autojunção:

SELECT t1.* FROM db.table t1
JOIN db.table t2 ON t1.someField = t2.someField AND t1.pk != t2.pk
Bill Karwin
fonte
11

Aqui está:

SELECT Field1, COUNT(Field1)
  FROM Table1 
 GROUP BY Field1
HAVING COUNT(Field1) > 1
ORDER BY Field1 desc
Nalan Madheswaran
fonte
4

Mão única

SELECT t1.* 
FROM db.table t1
WHERE exists 
      (SELECT *
      FROM db.table t2 
      where t1.pk != t2.pk 
      and t1.someField = t2.someField)
Martin Smith
fonte
1

Como OMG Ponies afirmou, a cláusula de ter é o que você está depois. No entanto, se você esperava obter linhas discretas em vez de um resumo (o "ter" cria um resumo) - isso não pode ser feito em uma única instrução. Você deve usar duas instruções nesse caso.

Brent Arias
fonte
1
Não é totalmente verdade - use o GROUP BY para manipular o que o HAVING está usando.
Pôneis OMG de
1

Dou um exemplo no Group By entre duas tabelas no Sql:

Select cn.name,ct.name,count(ct.id) totalcity from city ct left join country cn on ct.countryid = cn.id Group By cn.name,ct.name Having totalcity > 2


user4551254
fonte
1

Para mim, não ter um grupo por apenas retornou resultado vazio. Então eu acho que ter um grupo para a declaração de ter é muito importante

Maham Khan
fonte
-2

Também deve ser mencionado que o "pk" deve ser um campo chave. A auto-adesão

SELECT t1.* FROM db.table t1
JOIN db.table t2 ON t1.someField = t2.someField AND t1.pk != t2.pk 

por Bill Karwin dar-lhe todos os registros que são duplicados que é o que eu queria. Como alguns têm mais de dois, você pode obter o mesmo registro mais de uma vez. Eu escrevi tudo em outra tabela com os mesmos campos para me livrar dos mesmos registros por supressão de campos-chave. eu tentei

SELECT * FROM db.table HAVING COUNT(someField) > 1

acima primeiro. Os dados retornados fornecem apenas uma das duplicatas, menos da metade do que isso fornece, mas a contagem é boa se isso for tudo o que você deseja.

Jim Blanchard
fonte
3
Isso não é realmente uma resposta.
anon582847382