¿Eliminar todas las filas duplicadas excepto una en MySQL? [duplicar]

Resuelto Highway of Life asked hace 13 años • 2 respuestas

¿Cómo eliminaría todos los datos duplicados de una tabla MySQL?

Por ejemplo, con los siguientes datos:

SELECT * FROM names;

+----+--------+
| id | name   |
+----+--------+
| 1  | google |
| 2  | yahoo  |
| 3  | msn    |
| 4  | google |
| 5  | google |
| 6  | yahoo  |
+----+--------+

Lo usaría SELECT DISTINCT name FROM names;si fuera una SELECTconsulta.

¿Cómo haría esto DELETEpara eliminar solo los duplicados y mantener solo un registro de cada uno?

Highway of Life avatar Jan 14 '11 03:01 Highway of Life
Aceptado

Advertencia del editor: esta solución es computacionalmente ineficiente y puede interrumpir la conexión en una tabla grande.

NB: ¡ primero debe hacer esto en una copia de prueba de su tabla!

Cuando lo hice, descubrí que, a menos que también incluyera AND n1.id <> n2.id, eliminaba todas las filas de la tabla.

  1. Si desea mantener la fila con el idvalor más bajo:

    DELETE n1 FROM names n1, names n2 WHERE n1.id > n2.id AND n1.name = n2.name
    
  2. Si desea mantener la fila con el idvalor más alto:

    DELETE n1 FROM names n1, names n2 WHERE n1.id < n2.id AND n1.name = n2.name
    

Usé este método en MySQL 5.1

No estoy seguro de otras versiones.


Actualización: dado que las personas que buscan en Google para eliminar duplicados terminan aquí.
Aunque la pregunta del OP es sobre DELETE, tenga en cuenta que usar INSERTy DISTINCTes mucho más rápido. Para una base de datos con 8 millones de filas, la siguiente consulta tomó 13 minutos, mientras que usando DELETE, tomó más de 2 horas y aún así no se completó.

INSERT INTO tempTableName(cellId,attributeId,entityRowId,value)
    SELECT DISTINCT cellId,attributeId,entityRowId,value
    FROM tableName;
martin.masa avatar Feb 16 '2011 12:02 martin.masa

Si desea mantener la fila con el idvalor más bajo:

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MIN(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

Si quieres el idvalor que es el más alto:

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MAX(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

La subconsulta en una subconsulta es necesaria para MySQL o obtendrás un error 1093.

 avatar Jan 13 '2011 21:01