Eliminar filas duplicadas en MySQL


375

Tengo una tabla con los siguientes campos:

id (Unique)
url (Unique)
title
company
site_id

Ahora, necesito eliminar las filas que tienen lo mismo title, company and site_id. Una forma de hacerlo será usar el siguiente SQL junto con un script ( PHP):

SELECT title, site_id, location, id, count( * ) 
FROM jobs
GROUP BY site_id, company, title, location
HAVING count( * ) >1

Después de ejecutar esta consulta, puedo eliminar duplicados usando un script del lado del servidor.

Pero, quiero saber si esto se puede hacer solo usando la consulta SQL.


1
Pregunta rápida: ¿siempre desea que el duplicado (título, empresa, id_sitio) no exista? Si es así, establecería una restricción en la base de datos para exigir que title, company y site_id sean únicos. Lo que significaría que no necesitaría un proceso de limpieza. Y solo se necesita una sola línea de SQL.
J. Polfer

1
Consulte este enlace de stackoverflow . Funcionó para mí como un encanto.

Puedo recomendar esta solución (publicada en otro hilo): stackoverflow.com/a/4685232/195835
Simon East

También puede consultar esta respuesta
José Rui Santos,

Respuestas:


607

Una forma realmente fácil de hacer esto es agregar un UNIQUEíndice en las 3 columnas. Cuando escriba la ALTERdeclaración, incluya la IGNOREpalabra clave. Al igual que:

ALTER IGNORE TABLE jobs
ADD UNIQUE INDEX idx_name (site_id, title, company);

Esto eliminará todas las filas duplicadas. Como beneficio adicional, el futuro INSERTsque son duplicados será un error. Como siempre, es posible que desee realizar una copia de seguridad antes de ejecutar algo como esto ...


8
Interesante , pero los supuestos que hace la cláusula IGNORE para eliminar esos duplicados es una preocupación que podría no coincidir con las necesidades. ¿Le parecen buenos los valores incorrectos que se truncan en la coincidencia aceptable más cercana?
OMG Ponis

75
Solo para el registro si está usando InnoDB, entonces puede tener un problema con él, hay un error conocido sobre el uso de ALTER IGNORE TABLE con las bases de datos de InnoDB.
DarkMantis


42
Para las tablas de InnoDB, ejecute primero la siguiente consulta:set session old_alter_table=1;
shock_one

51
Esto ya no es compatible con 5.7.4, dev.mysql.com/doc/refman/5.7/en/alter-table.html
Ray Baxter

180

Si no desea alterar las propiedades de la columna, puede usar la consulta a continuación.

Como tiene una columna que tiene ID únicos (por ejemplo, auto_incrementcolumnas), puede usarla para eliminar los duplicados:

DELETE `a`
FROM
    `jobs` AS `a`,
    `jobs` AS `b`
WHERE
    -- IMPORTANT: Ensures one version remains
    -- Change "ID" to your unique column's name
    `a`.`ID` < `b`.`ID`

    -- Any duplicates you want to check for
    AND (`a`.`title` = `b`.`title` OR `a`.`title` IS NULL AND `b`.`title` IS NULL)
    AND (`a`.`company` = `b`.`company` OR `a`.`company` IS NULL AND `b`.`company` IS NULL)
    AND (`a`.`site_id` = `b`.`site_id` OR `a`.`site_id` IS NULL AND `b`.`site_id` IS NULL);

En MySQL, puede simplificarlo aún más con el operador igual seguro NULL (también conocido como "operador de nave espacial" ):

DELETE `a`
FROM
    `jobs` AS `a`,
    `jobs` AS `b`
WHERE
    -- IMPORTANT: Ensures one version remains
    -- Change "ID" to your unique column's name
    `a`.`ID` < `b`.`ID`

    -- Any duplicates you want to check for
    AND `a`.`title` <=> `b`.`title`
    AND `a`.`company` <=> `b`.`company`
    AND `a`.`site_id` <=> `b`.`site_id`;

3
esta solución no funciona correctamente, traté de hacer algunos registros duplicados y hace algo como (20 filas afectadas) pero si la ejecuta nuevamente, se mostrará (4 filas afectadas) y así sucesivamente hasta llegar a (0 filas afectadas) lo cual es un poco sospechoso y esto es lo que funciona mejor para mí, es casi lo mismo pero funciona de una sola vez, edité la solución
Nassim

1
@Nassim: Debes estar haciendo algo diferente a esta respuesta porque funciona perfectamente para mí (en MySQL).
Lawrence Dol

3
Para cualquiera que estuviera confundido como yo, los términos de comparación NULL son necesarios porque NULL no es igual a NULL en MySQL. Si se garantiza que las columnas relevantes no serán NULL, puede omitir estos términos.
Ian

3
Sí, la respuesta aceptada ya no es válida, ya que MYSQL 5.7 debería ser la respuesta aceptada, ya que es universal y tampoco requiere la creación temporal de tablas.
that-ben

1
MUY LENTO si hay MUCHAS copias de un registro dado (por ejemplo, 100 se reducirá a 1), y muchos registros con esa condición. Recomiende stackoverflow.com/a/4685232/199364 en su lugar. En mi humilde opinión, SIEMPRE utilice el enfoque vinculado; Es una técnica inherentemente más rápida.
ToolmakerSteve

78

MySQL tiene restricciones para referirse a la tabla de la que está eliminando. Puede solucionar eso con una tabla temporal, como:

create temporary table tmpTable (id int);

insert  into tmpTable
        (id)
select  id
from    YourTable yt
where   exists
        (
        select  *
        from    YourTabe yt2
        where   yt2.title = yt.title
                and yt2.company = yt.company
                and yt2.site_id = yt.site_id
                and yt2.id > yt.id
        );

delete  
from    YourTable
where   ID in (select id from tmpTable);

De la sugerencia de Kostanos en los comentarios:
La única consulta lenta anterior es ELIMINAR, para los casos en que tiene una base de datos muy grande. Esta consulta podría ser más rápida:

DELETE FROM YourTable USING YourTable, tmpTable WHERE YourTable.id=tmpTable.id

3
@andomar, esto funciona bien, excepto cuando uno de los campos en la cláusula where contiene valores nulos. Ejemplo: sqlfiddle.com/#!2/983f3/1
un codificador el

1
¿Insertar SQL es costoso? Me pregunto porque se agota el tiempo de espera en mi base de datos MySQL.
Cassio

44
La única consulta lenta aquí es ELIMINAR, en caso de que tenga una gran base de datos. Esta consulta podría ser más rápida:DELETE FROM YourTable USING YourTable, tmpTable WHERE YourTable.id=tmpTable.id
Kostanos

@Kostanos No solo DELETE, sino también INSERTa la mesa temporal, me llevó mucho tiempo. Entonces, un índice para la tabla tmp podría ayudar mucho create index tmpTable_id_index on tmpTable (id), al menos para mí.
Jiezhi.G

1
Si sus tablas son grandes, vale la pena agregar un índice con: -create temporary table tmpTable (id int, PRIMARY KEY (id));
Dallas Clarke el

44

Si la IGNOREdeclaración no funciona como en mi caso, puede usar la siguiente declaración:

CREATE TABLE your_table_deduped LIKE your_table;


INSERT your_table_deduped
SELECT *
FROM your_table
GROUP BY index1_id,
         index2_id;

RENAME TABLE your_table TO your_table_with_dupes;

RENAME TABLE your_table_deduped TO your_table;

#OPTIONAL
ALTER TABLE `your_table` ADD UNIQUE `unique_index` (`index1_id`, `index2_id`);

#OPTIONAL
DROP TABLE your_table_with_dupes;

1
funciona muy bien si tiene una configuración de innoDB con restricción de clave externa.
magdmartin

@magdmartin, pero ¿las restricciones externas no impedirán la eliminación de la tabla?
Basilevs

1
La declaración IGNORE no funcionó para mí y esto funcionó muy bien para deducir 5 millones de registros. Salud.
Mauvis Ledford

32

La eliminación de duplicados en las tablas de MySQL es un problema común, que generalmente es el resultado de una restricción que falta para evitar esos duplicados de antemano. Pero este problema común generalmente viene con necesidades específicas ... que requieren enfoques específicos. El enfoque debe ser diferente según, por ejemplo, el tamaño de los datos, la entrada duplicada que se debe mantener (generalmente la primera o la última), si hay índices que se deben mantener o si queremos realizar cualquier otro acción sobre los datos duplicados.

También hay algunas especificidades en MySQL en sí, como no poder hacer referencia a la misma tabla en una causa FROM al realizar una ACTUALIZACIÓN de tabla (generará el error de MySQL # 1093). Esta limitación se puede superar mediante el uso de una consulta interna con una tabla temporal (como se sugiere en algunos enfoques anteriores). Pero esta consulta interna no funcionará especialmente bien cuando se trata con grandes fuentes de datos.

Sin embargo, existe un mejor enfoque para eliminar duplicados, que es eficiente y confiable, y que puede adaptarse fácilmente a diferentes necesidades.

La idea general es crear una nueva tabla temporal, generalmente agregando una restricción única para evitar más duplicados, e INSERTAR los datos de su tabla anterior en la nueva, mientras se ocupan de los duplicados. Este enfoque se basa en consultas simples de INSERT de MySQL, crea una nueva restricción para evitar más duplicados y omite la necesidad de utilizar una consulta interna para buscar duplicados y una tabla temporal que debe mantenerse en la memoria (por lo tanto, también se ajustan a grandes fuentes de datos).

Así es como se puede lograr. Dado que tenemos una tabla de empleados , con las siguientes columnas:

employee (id, first_name, last_name, start_date, ssn)

Para eliminar las filas con una columna ssn duplicada y mantener solo la primera entrada encontrada, se puede seguir el siguiente proceso:

-- create a new tmp_eployee table
CREATE TABLE tmp_employee LIKE employee;

-- add a unique constraint
ALTER TABLE tmp_employee ADD UNIQUE(ssn);

-- scan over the employee table to insert employee entries
INSERT IGNORE INTO tmp_employee SELECT * FROM employee ORDER BY id;

-- rename tables
RENAME TABLE employee TO backup_employee, tmp_employee TO employee;

Explicación técnica

  • La línea # 1 crea una nueva tabla tmp_eployee con exactamente la misma estructura que la tabla de empleados
  • La línea # 2 agrega una restricción ÚNICA a la nueva tabla tmp_eployee para evitar más duplicados
  • La línea n. ° 3 explora la tabla de empleados original por id, insertando nuevas entradas de empleados en la nueva tabla tmp_eployee , mientras ignora las entradas duplicadas
  • La línea n. ° 4 cambia el nombre de las tablas, de modo que la nueva tabla de empleados contiene todas las entradas sin los duplicados, y una copia de seguridad de los datos anteriores se mantiene en la tabla backup_employee

Usando este enfoque, 1.6M registros se convirtieron en 6k en menos de 200s.

Chetan , siguiendo este proceso, puede eliminar rápida y fácilmente todos sus duplicados y crear una restricción ÚNICA ejecutando:

CREATE TABLE tmp_jobs LIKE jobs;

ALTER TABLE tmp_jobs ADD UNIQUE(site_id, title, company);

INSERT IGNORE INTO tmp_jobs SELECT * FROM jobs ORDER BY id;

RENAME TABLE jobs TO backup_jobs, tmp_jobs TO jobs;

Por supuesto, este proceso puede modificarse aún más para adaptarlo a diferentes necesidades al eliminar duplicados. Algunos ejemplos siguen.

✔ Variación para mantener la última entrada en lugar de la primera

A veces necesitamos mantener la última entrada duplicada en lugar de la primera.

CREATE TABLE tmp_employee LIKE employee;

ALTER TABLE tmp_employee ADD UNIQUE(ssn);

INSERT IGNORE INTO tmp_employee SELECT * FROM employee ORDER BY id DESC;

RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
  • En la línea # 3, la cláusula ORDER BY id DESC hace que las últimas ID tengan prioridad sobre el resto

✔ Variación para realizar algunas tareas en los duplicados, por ejemplo, llevar un recuento de los duplicados encontrados

A veces necesitamos realizar un procesamiento adicional en las entradas duplicadas que se encuentran (como mantener un recuento de los duplicados).

CREATE TABLE tmp_employee LIKE employee;

ALTER TABLE tmp_employee ADD UNIQUE(ssn);

ALTER TABLE tmp_employee ADD COLUMN n_duplicates INT DEFAULT 0;

INSERT INTO tmp_employee SELECT * FROM employee ORDER BY id ON DUPLICATE KEY UPDATE n_duplicates=n_duplicates+1;

RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
  • En la línea # 3, se crea una nueva columna n_duplicates
  • En la línea # 4, la consulta INSERT INTO ... ON DUPLICATE KEY UPDATE se usa para realizar una actualización adicional cuando se encuentra un duplicado (en este caso, aumentar un contador) La consulta INSERT INTO ... ON DUPLICATE KEY UPDATE puede ser Se utiliza para realizar diferentes tipos de actualizaciones para los duplicados encontrados.

✔ Variación para regenerar la identificación de campo incremental automático

A veces usamos un campo de incremento automático y, para mantener el índice lo más compacto posible, podemos aprovechar la eliminación de los duplicados para regenerar el campo de incremento automático en la nueva tabla temporal.

CREATE TABLE tmp_employee LIKE employee;

ALTER TABLE tmp_employee ADD UNIQUE(ssn);

INSERT IGNORE INTO tmp_employee SELECT (first_name, last_name, start_date, ssn) FROM employee ORDER BY id;

RENAME TABLE employee TO backup_employee, tmp_employee TO employee;
  • En la línea n. ° 3, en lugar de seleccionar todos los campos de la tabla, se omite el campo id para que el motor DB genere uno nuevo automáticamente

✔ Otras variaciones

Muchas modificaciones adicionales también son factibles dependiendo del comportamiento deseado. Como ejemplo, las siguientes consultas utilizarán una segunda tabla temporal para, además de 1) mantener la última entrada en lugar de la primera; y 2) aumentar un contador en los duplicados encontrados; también 3) regenere la identificación de campo incremental automático mientras mantiene el orden de entrada como estaba en los datos anteriores.

CREATE TABLE tmp_employee LIKE employee;

ALTER TABLE tmp_employee ADD UNIQUE(ssn);

ALTER TABLE tmp_employee ADD COLUMN n_duplicates INT DEFAULT 0;

INSERT INTO tmp_employee SELECT * FROM employee ORDER BY id DESC ON DUPLICATE KEY UPDATE n_duplicates=n_duplicates+1;

CREATE TABLE tmp_employee2 LIKE tmp_employee;

INSERT INTO tmp_employee2 SELECT (first_name, last_name, start_date, ssn) FROM tmp_employee ORDER BY id;

DROP TABLE tmp_employee;

RENAME TABLE employee TO backup_employee, tmp_employee2 TO employee;

27

Hay otra solución:

DELETE t1 FROM my_table t1, my_table t2 WHERE t1.id < t2.id AND t1.my_field = t2.my_field AND t1.my_field_2 = t2.my_field_2 AND ...

44
¿En qué se diferencia esto de la respuesta de @ rehriff, que presentó 6 meses antes?
Lawrence Dol

@LawrenceDol Supongo que es un poco más legible y también creo que su respuesta no fue la misma en el momento en que respondí y creo que su respuesta fue editada.
Mostafa -T

1
hmm ¡Me lleva demasiado tiempo mientras que la cantidad de registros no fue grande!
SuB

8

Si tiene una tabla grande con una gran cantidad de registros, las soluciones anteriores no funcionarán o tomarán demasiado tiempo. Entonces tenemos una solución diferente

-- Create temporary table

CREATE TABLE temp_table LIKE table1;

-- Add constraint
ALTER TABLE temp_table ADD UNIQUE(title, company,site_id);

-- Copy data
INSERT IGNORE INTO temp_table SELECT * FROM table1;

-- Rename and drop
RENAME TABLE table1 TO old_table1, temp_table TO table1;
DROP TABLE old_table1;

6

Tengo este snipet de consulta para SQLServer pero creo que se puede usar en otros DBMS con pequeños cambios:

DELETE
FROM Table
WHERE Table.idTable IN  (  
    SELECT MAX(idTable)
    FROM idTable
    GROUP BY field1, field2, field3
    HAVING COUNT(*) > 1)

Olvidé decirte que esta consulta no elimina la fila con la identificación más baja de las filas duplicadas. Si esto funciona para usted, intente esta consulta:

DELETE
FROM jobs
WHERE jobs.id IN  (  
    SELECT MAX(id)
    FROM jobs
    GROUP BY site_id, company, title, location
    HAVING COUNT(*) > 1)

Eso no funcionará si hay más de dos duplicados de un grupo.
OMG Ponis

11
Desafortunadamente, MySQL no permite que usted seleccione de la tabla que va a eliminar deERROR 1093: You can't specify target table 'Table' for update in FROM clause
Andomar

1
Para resolver el "You can't specify target table 'Table' for update in FROM..."error, use: DELETE FROM Table WHERE Table.idTable IN ( SELECT MAX(idTable) FROM (SELECT * FROM idTable) AS tmp GROUP BY field1, field2, field3 HAVING COUNT(*) > 1)que obliga a MySQL a crear una tabla temporal. Sin embargo, es muy lento en grandes conjuntos de datos ... en tales casos, recomendaré el código de Andomar, que es mucho más rápido.
lepe

6

La forma más rápida es insertar filas distintas en una tabla temporal. Usando eliminar, me tomó algunas horas eliminar duplicados de una tabla de 8 millones de filas. Usando inserto y distinto, tomó solo 13 minutos.

CREATE TABLE tempTableName LIKE tableName;  
CREATE INDEX ix_all_id ON tableName(cellId,attributeId,entityRowId,value);  
INSERT INTO tempTableName(cellId,attributeId,entityRowId,value) SELECT DISTINCT cellId,attributeId,entityRowId,value FROM tableName;  
TRUNCATE TABLE tableName;
INSERT INTO tableName SELECT * FROM tempTableName; 
DROP TABLE tempTableName;  

1
Tu cuarta línea debería decir TRUNCATE TABLE tableNamey la quinta línea debería decirINSERT INTO tableName SELECT * FROM tempTableName;
Sana

5

Una solución que es simple de entender y funciona sin clave primaria:

1) agregar una nueva columna booleana

alter table mytable add tokeep boolean;

2) agregue una restricción en las columnas duplicadas Y la nueva columna

alter table mytable add constraint preventdupe unique (mycol1, mycol2, tokeep);

3) establece la columna booleana en verdadero. Esto tendrá éxito solo en una de las filas duplicadas debido a la nueva restricción

update ignore mytable set tokeep = true;

4) eliminar filas que no se han marcado como mantenimiento

delete from mytable where tokeep is null;

5) suelte la columna agregada

alter table mytable drop tokeep;

Le sugiero que mantenga la restricción que agregó, para evitar nuevos duplicados en el futuro.


1
Esto funcionó muy bien en mysql 5.7, donde la solución aceptada ya no funciona
Robin31

5

Eliminar filas duplicadas usando la declaración DELETE JOIN MySQL le proporciona la declaración DELETE JOIN que puede usar para eliminar filas duplicadas rápidamente.

La siguiente instrucción elimina filas duplicadas y mantiene la identificación más alta:

DELETE t1 FROM contacts t1
    INNER JOIN
contacts t2 WHERE
t1.id < t2.id AND t1.email = t2.email;

5

Encontré una manera simple. (mantener lo último)

DELETE t1 FROM tablename t1 INNER JOIN tablename t2 
WHERE t1.id < t2.id AND t1.column1 = t2.column1 AND t1.column2 = t2.column2;

4

Simple y rápido para todos los casos:

CREATE TEMPORARY TABLE IF NOT EXISTS _temp_duplicates AS (SELECT dub.id FROM table_with_duplications dub GROUP BY dub.field_must_be_uniq_1, dub.field_must_be_uniq_2 HAVING COUNT(*)  > 1);

DELETE FROM table_with_duplications WHERE id IN (SELECT id FROM _temp_duplicates);

Código de error: 1055. La expresión # 2 de la lista SELECT no está en la cláusula GROUP BY y contiene la columna no agregada 'dub.id' que no depende funcionalmente de las columnas en la cláusula GROUP BY; esto es incompatible con sql_mode = only_full_group_by
Swoogan

puede deshabilitar el "control duro" con sql_mode, consulte stackoverflow.com/questions/23921117/disable-only-full-group-by
artemiuz el

4

Esto eliminará las filas duplicadas con los mismos valores para título, empresa y sitio. Se mantendrá la primera aparición y se eliminarán todos los duplicados.

DELETE t1 FROM tablename t1
INNER JOIN tablename t2 
WHERE 
    t1.id < t2.id AND
    t1.title = t2.title AND
    t1.company=t2.company AND
    t1.site_ID=t2.site_ID;

es lento (5w + filas, tiempo de espera de bloqueo) pero funcionó
yurenchen

3

Sigo visitando esta página cada vez que busco en Google "eliminar duplicados de mysql", pero para mis soluciones theIGNORE no funcionan porque tengo tablas de mysql de InnoDB

este código funciona mejor en cualquier momento

CREATE TABLE tableToclean_temp LIKE tableToclean;
ALTER TABLE tableToclean_temp ADD UNIQUE INDEX (fontsinuse_id);
INSERT IGNORE INTO tableToclean_temp SELECT * FROM tableToclean;
DROP TABLE tableToclean;
RENAME TABLE tableToclean_temp TO tableToclean;

tableToclean = el nombre de la tabla que necesita limpiar

tableToclean_temp = una tabla temporal creada y eliminada


2

Esta solución moverá los duplicados a una tabla y los únicos a otra .

-- speed up creating uniques table if dealing with many rows
CREATE INDEX temp_idx ON jobs(site_id, company, title, location);

-- create the table with unique rows
INSERT jobs_uniques SELECT * FROM
    (
    SELECT * 
    FROM jobs
    GROUP BY site_id, company, title, location
    HAVING count(1) > 1
    UNION
    SELECT *
    FROM jobs
    GROUP BY site_id, company, title, location
    HAVING count(1) = 1
) x

-- create the table with duplicate rows
INSERT jobs_dupes 
SELECT * 
FROM jobs
WHERE id NOT IN
(SELECT id FROM jobs_uniques)

-- confirm the difference between uniques and dupes tables
SELECT COUNT(1)
AS jobs, 
(SELECT COUNT(1) FROM jobs_dupes) + (SELECT COUNT(1) FROM jobs_uniques)
AS sum
FROM jobs

¿Por qué tomaste la unión y no solo SELECT * FROM jobs GROUP BY site_id, company, title, location?
timctran 01 de

2

A partir de la versión 8.0 (2018), MySQL finalmente admite funciones de ventana .

Las funciones de la ventana son prácticas y eficientes. Aquí hay una solución que demuestra cómo usarlos para resolver esta tarea.

En una subconsulta, podemos usar ROW_NUMBER()para asignar una posición a cada registro en la tabla dentro de column1/column2grupos, ordenados por id. Si no hay duplicados, el registro obtendrá el número de fila 1. Si existe un duplicado, se numerarán de forma ascendente id(comenzando en 1).

Una vez que los registros se numeran correctamente en la subconsulta, la consulta externa simplemente elimina todos los registros cuyo número de fila no es 1.

Consulta :

DELETE FROM tablename
WHERE id IN (
    SELECT id
    FROM (
        SELECT 
            id, 
            ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id) rn
        FROM output
    ) t
    WHERE rn > 1
)

1

Para eliminar el registro duplicado en una tabla.

delete from job s 
where rowid < any 
(select rowid from job k 
where s.site_id = k.site_id and 
s.title = k.title and 
s.company = k.company);

o

delete from job s 
where rowid not in 
(select max(rowid) from job k 
where s.site_id = k.site_id and
s.title = k.title and 
s.company = k.company);

1
-- Here is what I used, and it works:
create table temp_table like my_table;
-- t_id is my unique column
insert into temp_table (id) select id from my_table GROUP by t_id;
delete from my_table where id not in (select id from temp_table);
drop table temp_table;

0

Para duplicar registros con columnas únicas, por ejemplo, COL1, COL2, COL3 no deben replicarse (supongamos que hemos perdido 3 columnas únicas en la estructura de la tabla y se han realizado múltiples entradas duplicadas en la tabla)

DROP TABLE TABLE_NAME_copy;
CREATE TABLE TABLE_NAME_copy LIKE TABLE_NAME;
INSERT INTO TABLE_NAME_copy
SELECT * FROM TABLE_NAME
GROUP BY COLUMN1, COLUMN2, COLUMN3; 
DROP TABLE TABLE_NAME;
ALTER TABLE TABLE_NAME_copy RENAME TO TABLE_NAME;

La esperanza ayudará a los desarrolladores.


0

TL; TR;

Puede encontrar un tutorial ampliamente descrito para resolver este problema en el sitio mysqltutorial.org :

Cómo eliminar filas duplicadas en MySQL

Se muestra muy claramente cómo eliminar filas duplicadas de tres maneras diferentes :

A) Uso de la DELETE JOINdeclaración

B) Usando una tabla intermedia

C) Uso de la ROW_NUMBER()función

Espero que ayude a alguien.


0

Tengo una tabla que olvida agregar una clave principal en la fila de id. Aunque tiene auto_increment en la identificación. Pero un día, una cosa reproduce el registro de mysql bin en la base de datos que inserta algunas filas duplicadas.

Elimino la fila duplicada por

  1. seleccione las filas duplicadas únicas y expórtelas

select T1.* from table_name T1 inner join (select count(*) as c,id from table_name group by id) T2 on T1.id = T2.id where T2.c > 1 group by T1.id;

  1. eliminar las filas duplicadas por id

  2. inserte la fila de los datos exportados.

  3. Luego agregue la clave principal en la identificación


-2

Me gusta ser un poco más específico en cuanto a qué registros elimino, así que aquí está mi solución:

delete
from jobs c1
where not c1.location = 'Paris'
and  c1.site_id > 64218
and exists 
(  
select * from jobs c2 
where c2.site_id = c1.site_id
and   c2.company = c1.company
and   c2.location = c1.location
and   c2.title = c1.title
and   c2.site_id > 63412
and   c2.site_id < 64219
)

-4

Puede eliminar fácilmente los registros duplicados de este código.

$qry = mysql_query("SELECT * from cities");
while($qry_row = mysql_fetch_array($qry))
{
$qry2 = mysql_query("SELECT * from cities2 where city = '".$qry_row['city']."'");

if(mysql_num_rows($qry2) > 1){
    while($row = mysql_fetch_array($qry2)){
        $city_arry[] = $row;

        }

    $total = sizeof($city_arry) - 1;
        for($i=1; $i<=$total; $i++){


            mysql_query( "delete from cities2 where town_id = '".$city_arry[$i][0]."'");

            }
    }
    //exit;
}

3
Esta es una muy mala forma: las tareas de la base de datos deben realizarse en la base de datos, donde son mucho más rápidas, en lugar de enviar datos constantemente entre php / mysql porque conoces una mejor que la otra.
Max

-4

Tuve que hacer esto con campos de texto y encontré el límite de 100 bytes en el índice.

Resolví esto agregando una columna, haciendo un hash md5 de los campos y haciendo el alter.

ALTER TABLE table ADD `merged` VARCHAR( 40 ) NOT NULL ;
UPDATE TABLE SET merged` = MD5(CONCAT(`col1`, `col2`, `col3`))
ALTER IGNORE TABLE table ADD UNIQUE INDEX idx_name (`merged`);
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.