Видаліть повторювані рядки в MySQL


375

У мене є таблиця з такими полями:

id (Unique)
url (Unique)
title
company
site_id

Тепер мені потрібно видалити такі ж рядки title, company and site_id. Одним із способів зробити це буде використання наступного SQL разом із скриптом ( PHP):

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

Після запуску цього запиту я можу видалити дублікати за допомогою скрипту на стороні сервера.

Але я хочу знати, чи можна це зробити лише за допомогою SQL-запиту.


1
Швидке запитання: чи завжди потрібно, щоб дублікат (назва, компанія, сайт_id) не існував? Якщо так, я б встановив обмеження в базі даних, щоб примусити назву, компанію та site_id бути унікальними. Що означає, що вам не знадобиться процес очищення. І це займає лише один рядок SQL.
Дж. Полфер

1
Будь ласка, перейдіть за цим посиланням stackoverflow . Це працювало для мене як шарм.

Я можу порекомендувати це рішення (розміщено в іншій темі): stackoverflow.com/a/4685232/195835
Simon East

Ви також можете перевірити цю відповідь
Хосе Руй Сантос

Відповіді:


607

Дійсно простий спосіб зробити це - додати UNIQUEіндекс у 3 стовпці. Коли ви пишете ALTERзаяву, додайте IGNOREключове слово. Так:

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

Це скине всі повторювані рядки. В якості додаткової переваги майбутні INSERTsдублікати помиляться. Як завжди, можливо, захочете зробити резервну копію, перш ніж запустити щось подібне ...


8
Цікаво , але припущення, які додає пункт IGNORE для видалення цих дублікатів, викликають занепокоєння, яке може не відповідати потребам. Неправильні значення, прив’язані до найближчого прийнятного відповідника, звучать добре для вас?
OMG Ponies

75
Тільки для запису, якщо ви користуєтесь InnoDB, то у вас можуть виникнути проблеми з ним, є відома помилка щодо використання ALTER IGNORE TABLE з базами даних InnoDB.
DarkMantis


42
Для таблиць InnoDB спочатку виконайте такий запит:set session old_alter_table=1;
shock_one


180

Якщо ви не хочете змінювати властивості стовпця, то можете скористатись запитом нижче.

Оскільки у вас є стовпець з унікальними ідентифікаторами (наприклад, auto_incrementстовпчики), ви можете використовувати його для видалення дублікатів:

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);

У MySQL ви можете ще більше спростити його за допомогою NULL-безпечного рівного оператора (він же "оператор космічного корабля" ):

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
це рішення не працює належним чином, я спробував зробити кілька повторних записів, і він робить щось на кшталт (зачеплене 20 рядків), але якщо запустити його знову, воно покаже вам (4 рядки зачеплені) і так далі, поки ви не досягнете (0 рядків зачеплені) яка ні з чим підозріла, і ось що для мене найкраще працює, це майже те саме, але воно працює за один раз, я відредагував рішення
Нассім

1
@Nassim: Ви повинні робити щось інше, ніж ця відповідь, тому що вона прекрасно працює для мене (в MySQL).
Лоуренс Дол

3
Для тих, хто плутався як і я, потрібні умови порівняння NULL, оскільки NULL не дорівнює NULL в MySQL. Якщо відповідні стовпці гарантовано не становлять NULL, ви можете залишити ці умови поза межами.
Ян

3
Так, прийнята відповідь більше не є дійсною, оскільки MYSQL 5.7, тому це дійсно має бути прийнятою відповіддю, оскільки вона є універсальною і не вимагає також створення тимчасової таблиці.
що-бен

1
ДУЖЕ СЛІД, якщо є МНОГО копій даного запису (наприклад, 100 буде зменшено до 1), і багато записів з цією умовою. Рекомендуйте натомість stackoverflow.com/a/4685232/199364 . ІМХО, ВИНАГИ використовують зв’язаний підхід; це по суті більш швидка техніка.
ToolmakerSteve

78

У MySQL є обмеження щодо посилання на таблицю, з якої ви видаляєте. Ви можете обійти це тимчасовим столом, як:

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);

З пропозиції Костаноса в коментарях:
Єдиний повільний запит, наведений вище, - DELETE, для випадків, коли у вас дуже велика база даних. Цей запит може бути швидшим:

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

3
@andomar, це працює чудово, за винятком випадків, коли одне з полів у пункті, де містяться нулі. Приклад: sqlfiddle.com/#!2/983f3/1
кодер

1
Чи є Insert SQL дорогим? Мені цікаво, бо час у моїй базі даних MySQL закінчується.
Кассіо

4
Єдиний повільний запит тут - ВИДАЛИТИ один, якщо у вас є велика база даних. Цей запит міг бути швидшим:DELETE FROM YourTable USING YourTable, tmpTable WHERE YourTable.id=tmpTable.id
Костанос

@Kostanos Не тільки DELETE, але і INSERTдо тимчасового столу, це зайняло у мене багато часу. Тож індекс для tmp table міг би дуже допомогти create index tmpTable_id_index on tmpTable (id), принаймні для мене.
Jiezhi.G

1
Якщо ваші таблиці великі, варто дико додати індекс із: -create temporary table tmpTable (id int, PRIMARY KEY (id));
Даллас Кларк

44

Якщо IGNOREвислів не працюватиме, як у моєму випадку, ви можете скористатися наведеним нижче твердженням:

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
чудово працює, якщо у вас є налаштування nedinBB із обмеженням зовнішнього ключа.
magdmartin

@magdmartin, але чи не будуть зовнішні обмеження перешкоджати видаленню таблиці?
Василевс

1
Заява IGNORE не працювала для мене, і це чудово спрацювало над тим, щоб вивести 5 мільйонів записів. Ура.
Mauvis Ledford

32

Видалення дублікатів у таблицях MySQL є поширеною проблемою, це взагалі результат відсутнього обмеження, щоб уникнути цих дублікатів перед рукою. Але це поширене питання зазвичай виникає з конкретними потребами ..., які вимагають конкретних підходів. Підхід повинен бути різним залежно, наприклад, від розміру даних, дубльованого запису, який слід зберігати (як правило, перший чи останній), чи є індекси, які потрібно зберігати, чи ми хочемо виконати якісь додаткові дії на дублювані дані.

Існує також деякі особливості самого MySQL, наприклад, неможливість посилання на ту саму таблицю на причину FROM під час виконання таблиці UPDATE (це призведе до помилки MySQL №1093). Це обмеження можна подолати, використовуючи внутрішній запит із тимчасовою таблицею (як це пропонується у деяких підходах вище). Але цей внутрішній запит не працюватиме особливо добре при роботі з великими джерелами даних.

Однак існує кращий підхід до видалення дублікатів, який є і ефективним, і надійним, і його можна легко адаптувати до різних потреб.

Загальна ідея полягає у створенні нової тимчасової таблиці, зазвичай додаючи унікальне обмеження, щоб уникнути подальших дублікатів, і ВСТАВИТИ дані з колишньої таблиці в нову, доглядаючи за дублікатами. Цей підхід покладається на прості запити MySQL INSERT, створює нове обмеження, щоб уникнути подальших дублікатів, і пропускає необхідність використання внутрішнього запиту для пошуку дублікатів та тимчасової таблиці, яка повинна зберігатися в пам'яті (таким чином, підпадаючи і до великих джерел даних).

Ось як це можна досягти. З огляду на те, що у нас є співробітник таблиці із наступними стовпцями:

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

Для того, щоб видалити рядки з повторюваного стовпця ssn та зберегти лише знайдений перший запис, можна дотримуватися наступного процесу:

-- 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;

Технічне пояснення

  • Рядок №1 створює нову таблицю tmp_eployee з точно такою ж структурою, як таблиця службовців
  • Рядок №2 додає Унікальне обмеження до нової таблиці tmp_eployee, щоб уникнути подальших дублікатів
  • Рядок №3 сканує над початковою таблицею службовців за допомогою id, вставляючи нові записи співробітників у нову таблицю tmp_eployee , ігноруючи повторювані записи
  • Рядок №4 перейменовує таблиці, так що нова таблиця співробітників зберігає всі записи без дублікатів, а резервна копія колишніх даних зберігається в таблиці backup_employee

Використовуючи цей підхід, 1,6М регістри були перетворені на 6k менш ніж за 200 років.

Четан , дотримуючись цього процесу, ви можете швидко і легко видалити всі свої дублікати і створити єдине обмеження, запустивши:

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;

Звичайно, цей процес можна додатково модифікувати, щоб адаптувати його до різних потреб при видаленні дублікатів. Деякі приклади випливають.

✔ Варіант збереження останнього запису замість першого

Іноді нам потрібно зберегти останній дублюваний запис замість першого.

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;
  • У рядку №3 пункт ORDER BY id DESC робить останній ідентифікатор, щоб отримати пріоритет перед іншими

Варіант виконання деяких завдань над дублікатами, наприклад, підрахунок знайдених дублікатів

Іноді нам потрібно здійснити деяку подальшу обробку знайдених дублюваних записів (наприклад, збереження кількості дублікатів).

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;
  • У рядку # 3, новий стовпець n_duplicates створюється
  • У рядку №4 запит ВСТАВИТИ У ДУПЛІКАТИ КЛЮЧОВОГО ОБНОВЛЕННЯ запит використовується для здійснення додаткового оновлення, коли буде знайдено дублікат (у цьому випадку збільшується лічильник) ВСТАВКА У ВІД ... НА ДУПЛІКАТИ КЛЮЧНО ОНОВЛЕННЯ запит може бути використовується для виконання різних типів оновлень для знайдених дублікатів.

✔ Варіант для відновлення ідентифікатора автоматичного збільшення поля

Іноді ми використовуємо поле з автоматичним збільшенням, і для того, щоб індекс був максимально компактним, ми можемо скористатись видаленням дублікатів для відновлення авто-додаткового поля в новій тимчасовій таблиці.

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;
  • У рядку №3 замість вибору всіх полів таблиці поле id пропускається, щоб двигун БД автоматично генерував нове

✔ Подальші зміни

Багато інших модифікацій також можливі в залежності від бажаної поведінки. Наприклад, наступні запити використовуватимуть другу тимчасову таблицю, щоб, крім 1) зберегти останній запис замість першого; та 2) збільшити лічильник на знайдених дублікатах; також 3) відновити автоматичний додатковий ідентифікатор поля, зберігаючи порядок введення, як це було у попередніх даних.

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

Є ще одне рішення:

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 ...

4
Чим це відрізняється від відповіді @ rehriff, яку він подав на 6 місяців раніше?
Лоуренс Дол

@LawrenceDol Я думаю, що це трохи читабельніше, а також я думаю, що його відповідь була не однаковою в той час, коли я відповів, і я думаю, що його відповідь була відредагована.
Мостафа -T

1
хм. Мені це зайняло занадто багато часу, поки кількість записів була не великою!
SuB

8

якщо у вас є велика таблиця з величезною кількістю записів, то вищевикладені рішення не спрацюють або не займуть багато часу. Тоді у нас інше рішення

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

У мене є цей фрагмент запиту для SQLServer, але я думаю, що його можна використовувати в інших СУБД з невеликими змінами:

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

Я забув сказати вам, що цей запит не видаляє рядок із найменшим ідентифікованим рядком. Якщо це працює для вас, спробуйте цей запит:

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

Це не спрацює, якщо в групі більше двох дублів.
OMG Ponies

11
На жаль, MySQL не дозволяє вибрати з таблиці, з якої ви видаляєтеERROR 1093: You can't specify target table 'Table' for update in FROM clause
Andomar

1
Щоб вирішити "You can't specify target table 'Table' for update in FROM..."помилку, використовуйте: DELETE FROM Table WHERE Table.idTable IN ( SELECT MAX(idTable) FROM (SELECT * FROM idTable) AS tmp GROUP BY field1, field2, field3 HAVING COUNT(*) > 1)що змушує MySQL створити часову таблицю. Однак у великих наборах даних це дуже повільно ... в таких випадках я рекомендую код Андомара, який набагато швидше.
lepe

6

Швидший спосіб - вставити окремі рядки у тимчасову таблицю. Використовуючи видалення, мені знадобилося кілька годин, щоб видалити дублікати з таблиці в 8 мільйонів рядків. Використовуючи вставку та чітко, це зайняло всього 13 хвилин.

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
Ваш четвертий рядок повинен сказати, TRUNCATE TABLE tableNameа 5-й рядокINSERT INTO tableName SELECT * FROM tempTableName;
Сана

5

Рішення, яке легко зрозуміти і працює без первинного ключа:

1) додати новий булевий стовпчик

alter table mytable add tokeep boolean;

2) додати обмеження на дублювані стовпці ТА новий стовпець

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

3) встановити булеву колонку в істинне. Це вдасться досягти лише в одному з дублюваних рядків через нове обмеження

update ignore mytable set tokeep = true;

4) видалити рядки, які не були позначені як зйомка

delete from mytable where tokeep is null;

5) опустити доданий стовпчик

alter table mytable drop tokeep;

Я пропоную вам зберегти додане вами обмеження, щоб уникнути нових дублікатів у майбутньому.


1
Це справді добре працювало в mysql 5.7, де прийняте рішення більше не працює
Robin31

5

Видалення повторюваних рядків за допомогою оператора DELETE JOIN MySQL надає вам операцію DELETE JOIN, яку ви можете використовувати для швидкого видалення повторюваних рядків.

Наступне твердження видаляє повторювані рядки і зберігає найвищий ідентифікатор:

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

5

Я знайшов простий спосіб. (тримай останнє)

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

Простий і швидкий для всіх випадків:

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);

Код помилки: 1055. Вираз №2 у списку SELECT відсутній у пункті GROUP BY і містить неагреговану колонку 'dub.id', яка функціонально не залежить від стовпців у пункті GROUP BY; це несумісно з sql_mode = only_full_group_by
Swoogan

Ви можете відключити «жорсткий контроль» з sql_mode см stackoverflow.com/questions/23921117/disable-only-full-group-by
artemiuz

4

Це видалить повторювані рядки з однаковими значеннями для заголовка, компанії та сайту. Перше виникнення буде збережено, а решта всіх дублікатів буде видалено

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;

це повільно (5w + рядки, блокування очікування очікування блокування), але працювало
yurenchen

3

Я постійно відвідую цю сторінку в будь-який час, коли я google "видалити дублікати форми mysql", але для моїх рішень THEIGNORE не працюють, тому що у мене є таблиці mysql InnoDB

цей код працює краще будь-коли

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 = назва таблиці, яку потрібно очистити

tableToclean_temp = створена та видалена тимчасова таблиця


2

Це рішення перемістить дублікати в одну таблицю, а унікальні - в іншу .

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

Чому ви взяли союз, а не просто SELECT * FROM jobs GROUP BY site_id, company, title, location?
timctran

2

Станом на версію 8.0 (2018), MySQL нарешті підтримує функції вікон .

Функції вікон зручні та ефективні. Ось рішення, яке демонструє, як їх використовувати для вирішення цього завдання.

У підзапиті ми можемо використовувати ROW_NUMBER()для призначення позиції кожному запису в таблиці в межах column1/column2груп, упорядкованих користувачем id. Якщо дублікатів немає, запис отримає номер рядка 1. Якщо існує дублікат, вони пронумеруються за зростанням id(починаючи з1 ).

Після того, як записи належним чином пронумеровані в підзапиті, зовнішній запит просто видаляє всі записи, номер рядка яких не 1.

Запит:

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

Щоб видалити повторюваний запис у таблиці.

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);

або

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

Для дублювання записів унікальними стовпцями, наприклад, COL1, COL2, COL3, не слід реплікувати (припустимо, ми пропустили 3 унікальних стовпця в структурі таблиці, і в таблицю було внесено кілька дублікатів)

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;

Надія допоможе дев.


0

TL; TR;

Широко описаний підручник для вирішення цієї проблеми можна знайти на mysqltutorial.org сайті :

Як видалити повторювані рядки в MySQL

Дуже чітко показано, як видалити повторювані рядки трьома різними способами :

А) ВикористанняDELETE JOIN оператора

Б) Використання проміжної таблиці

В) ВикористанняROW_NUMBER() функції

Я сподіваюся, що це комусь допоможе.


0

У мене є таблиця, яка забула додати первинний ключ у рядку id. Хоча має ідентифікатор auto_increment. Але одного дня один матеріал повторює журнал бін mysql у базі даних, куди вставляються кілька повторюваних рядків.

Я видаляю повторюваний рядок на

  1. виберіть унікальні дублікати рядків та експортуйте їх

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. видаліть повторювані рядки за ідентифікатором

  2. вставити рядок із експортованих даних.

  3. Потім додайте первинний ключ на id


-2

Мені подобається бути трохи більш конкретним щодо записів, які я видаляю, ось ось моє рішення:

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

Ви можете легко видалити повторювані записи з цього коду ..

$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
Це дуже погано. Завдання бази даних повинні виконуватися в БД, де вони набагато швидше, а не постійно надсилати дані між php / mysql, оскільки ви знаєте одне краще, ніж інше.
Макс

-4

Мені довелося це зробити з текстовими полями і натрапив на обмеження в 100 байт.

Я вирішив це, додавши стовпчик, зробивши хеш md5 полів і зробивши 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`);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.