Seleccione dónde el recuento de un campo es mayor que uno

100

Quiero hacer algo como esto:

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

¿Cómo puedo lograr esto en MySql?

stevebot
fuente

Respuestas:

146

Utilice la cláusula HAVING, not WHERE, para la comparación de resultados agregados.

Tomando la consulta al pie de la letra:

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

Idealmente, debería haber un GROUP BYdefinido para una valoración adecuada en la HAVINGcláusula, pero MySQL permite columnas ocultas del GROUP BY ...

¿Es esto en preparación para una restricción única someField? Parece que debería ser ...

Ponis dios mio
fuente
11
¿Necesita un GROUP BYseguro (a menos que esto sea algo de MySQL no estándar)?
Martin Smith
@Martin Smith: tomó la consulta al pie de la letra; Se solucionó el problema GROUP BY (incluida la función de columnas ocultas).
OMG Ponies
"Parece que debería ser ..." ¿Por qué? Necesito educación sobre esto :)
Dave
Entonces, esto devolverá la tabla completa si contiene más de 2 someFieldvalores no nulos o un conjunto de resultados vacío si no lo hace.
Martin Smith
@Dave: Si estuviera en una posición en la que tuviera que verificar y corregir periódicamente los datos incorrectos, ¿no le gustaría evitar que la situación suceda en primer lugar? MySQL implementa una restricción única como índice; para obtener más información, consulte la documentación de CREATE INDEX
OMG Ponies
18
SELECT username, numb from(
Select username, count(username) as numb from customers GROUP BY username ) as my_table
WHERE numb > 3
dandy_sql
fuente
3
la única advertencia aquí (al menos en 5.1.46-community MySQL Community Server (GPL)) es que "Cada tabla derivada debe tener su propio alias", que hará que su sql se vea como: SELECT username, entumecido de (Seleccionar nombre de usuario, count (username) como insensible de los clientes GROUP BY username) como my_table WHERE numb> 3
D_K
14

También puede hacer esto con una autounión:

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

Aqui tienes:

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

De una sola mano

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
fuente
1

Como dijo OMG Ponies, la cláusula de tener es lo que buscas. Sin embargo, si esperaba obtener filas discretas en lugar de un resumen (el "tener" crea un resumen), no se puede hacer en una sola declaración. Debe usar dos declaraciones en ese caso.

Brent Arias
fuente
1
No es del todo cierto: use GROUP BY para manipular lo que HAVING está usando.
OMG Ponies
1

Doy un ejemplo en Group By entre dos tablas en 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


usuario4551254
fuente
1

Para mí, no tener un grupo simplemente devolvió un resultado vacío. Así que supongo que tener un grupo para la declaración de tener es bastante importante

Maham Khan
fuente
-2

También debe mencionarse que el "pk" debe ser un campo clave. La autounión

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

de Bill Karwin te doy todos los registros que son duplicados que es lo que quería. Debido a que algunos tienen más de dos, puede obtener el mismo registro más de una vez. Escribí todo en otra tabla con los mismos campos para deshacerme de los mismos registros mediante la supresión de campos clave. Lo intenté

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

arriba primero. Los datos devueltos dan solo uno de los duplicados, menos de la mitad de lo que esto le brinda, pero el recuento es bueno si eso es todo lo que desea.

Jim Blanchard
fuente
3
Esta no es realmente una respuesta.
anon582847382