2010-09-08 25 views
13

Tengo una tabla de datos y hay muchas entradas duplicadas de las presentaciones de los usuarios.Eliminar filas duplicadas dejando la fila más antigua ¿Solo?

Quiero eliminar todas las filas duplicadas según el campo subscriberEmail, dejando solo el envío original.

En otras palabras, quiero buscar todos los correos duplicados y eliminar esas filas, dejando solo el original.

¿Cómo puedo hacer esto sin cambiar las tablas?
Mi tabla contiene identificadores únicos para cada fila.

+0

Usted debe marque una respuesta como "aceptada" :-) – watery

Respuesta

27

Dado que está utilizando la columna id como un indicador de qué registro es 'original':

delete x 
from myTable x 
join myTable z on x.subscriberEmail = z.subscriberEmail 
where x.id > z.id 

Esto dejará un registro por e-mail.

de edición para añadir:

para explicar la consulta anterior ...

La idea aquí es unirse a la mesa contra sí mismo. Imagine que tiene dos copias de la tabla, cada una llamada algo diferente. Luego, puede compararlos entre sí y encontrar la identificación más baja o para cada dirección de correo electrónico. A continuación, vería los registros duplicados que se crearon más adelante y podría eliminarlos. (Estaba visualizando Excel al pensar en esto.)

Para hacer esa operación en una tabla, compararla consigo mismo y ser capaz de identificar cada lado, use alias de tabla. x es un alias de tabla. Se asigna en la cláusula from como lo siguiente: from <table> <alias>. x ahora se puede utilizar en otra parte de la misma consulta para hacer referencia a esa tabla como un acceso directo.

delete x comienza la consulta con nuestra acción y objetivo. Vamos a realizar una consulta para seleccionar registros de varias tablas, y queremos eliminar registros que aparecen en x.

Los alias se utilizan para referirse a ambas 'instancias' de la tabla. from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail golpea la tabla contra sí misma donde coinciden los correos electrónicos. Sin la cláusula where que sigue, cada registro se seleccionaría ya que podría unirse entre sí.

La cláusula where limita los registros que se seleccionan. where x.id > z.id permite que la 'instancia' con alias x contenga solo los registros que coinciden con los correos electrónicos pero tiene un valor id más alto. Los datos que realmente desea en la tabla, las direcciones de correo electrónico únicas (con la identificación más baja) no serán parte de x y no se eliminarán. Los únicos registros en x serán registros duplicados (direcciones de correo electrónico) que tengan un id más alto que el registro original para esa dirección de correo electrónico.

la unión y donde cláusulas podrían combinarse en este caso:

delete x 
    from myTable x 
    join myTable z 
    on x.subscriberEmail = z.subscriberEmail 
     and x.id > z.id 

Para la prevención de duplicados, considerar la posibilidad de la columna de la subscriberEmail una columna indexada ÚNICA.

+0

Oye, no entiendo qué es X en esto, y dónde se ingresa la fecha. Podría usar ID ya que hay ID primario establecido para cada uno o fecha. ID suena más fácil –

+0

¡Oye, funcionó! Cambié "createdOn" a "id" y ¡listo! jaja gracias - Aquí está el código que utilicé en PHP: mysql_query ("borrar x de my_table x unen z = my_table en x.subscriberEmail z.subscriberEmail donde x.id> z.id") or die (mysql_error ()); –

+0

¿Puede explicar cómo leer este código en inglés? Ayuda a poder leer lógicamente algo para comprender la sintaxis. Además, ¿cómo puedo prevenir los duplicados en primer lugar? Ya estoy usando Insertar IGNORAR pero no ignora –

0

Si tiene una identificación única para cada fila, puede intentar algo como esto. No me preguntes por qué exactamente necesitas la segunda instrucción de selección, mysql no me permitirá ejecutar de otra manera. Además, agrupe según las columnas que hagan que sus resultados sean únicos.

delete from my_table where id in (
    select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1 
) b 
); 
+1

Creo que esto eliminaría todos ellos, no solo los extras. – Fosco

+0

No, no lo haría. El grupo by agrupará como filas por subscriberEmail. Por lo tanto, se seleccionará un suscriptor con más de 1 correo electrónico (con el recuento (*)> 1). En este punto, prácticamente tiene un conjunto de registros distinto de suscriptores con más de 1 correo electrónico. Tome la identificación de este conjunto de registros y elimínela. Lo intenté y funciona como un encanto. –

+0

Ejecutando este código produce el error "# 1064 - Usted tiene un error en su sintaxis SQL, revise el manual que corresponde a su versión del servidor MySQL para la sintaxis correcta para usar cerca de '' en la línea 2" - Código debajo de –

1

¿Qué tal esto, ahora no es necesario que crear las tablas temporales mediante auto une

DELETE u1 FROM users u1, users u2 WHERE u1.id < u2.id AND u1.email = u2.email 

Para comprobar si hay registros duplicados en la tabla

SELECT count(*) as Count, email FROM users u group by email having Count > 1 
Cuestiones relacionadas