Мені потрібно DELETE
дублювати рядки для вказаного sid на aMySQL
столі.
Як я можу це зробити за допомогою SQL-запиту?
DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"
Щось подібне, але я не знаю, як це зробити.
Мені потрібно DELETE
дублювати рядки для вказаного sid на aMySQL
столі.
Як я можу це зробити за допомогою SQL-запиту?
DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"
Щось подібне, але я не знаю, як це зробити.
Відповіді:
це видаляє дублікати на місці, не створюючи нової таблиці
ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)
Примітка: добре працює лише в тому випадку, якщо індекс вписується в пам'ять
ALTER IGNORE
.
ALTER TABLE foo ENGINE MyISAM
працювати навколо цього, після змінив двигун.
Припустимо, у вас є таблиця employee
із такими стовпцями:
employee (first_name, last_name, start_date)
Щоб видалити рядки з повторюваним first_name
стовпцем:
delete
from employee using employee,
employee e1
where employee.id > e1.id
and employee.first_name = e1.first_name
employee
проти себе для одного індечного матчу та одна >
перевірка індексу буде повільною для великих таблиць. Не було б краще , SELECT MAX(ID) FROM t GROUP BY unique
а потім JOIN
на точний збіг ID
з MAX(ID)
?
Після видалення дублікатів для всіх SID, не тільки одного.
З темп-таблицею
CREATE TABLE table_temp AS
SELECT * FROM table GROUP BY title, SID;
DROP TABLE table;
RENAME TABLE table_temp TO table;
Оскільки temp_table
свіжо створений, він не має індексів. Вам потрібно буде відтворити їх після видалення дублікатів. Ви можете перевірити, з якими індексами є таблицяSHOW INDEXES IN table
Без таблиці темп:
DELETE FROM `table` WHERE id IN (
SELECT all_duplicates.id FROM (
SELECT id FROM `table` WHERE (`title`, `SID`) IN (
SELECT `title`, `SID` FROM `table` GROUP BY `title`, `SID` having count(*) > 1
)
) AS all_duplicates
LEFT JOIN (
SELECT id FROM `table` GROUP BY `title`, `SID` having count(*) > 1
) AS grouped_duplicates
ON all_duplicates.id = grouped_duplicates.id
WHERE grouped_duplicates.id IS NULL
)
SELECT * FROM table GROUP BY title, SID;
Все залежить від того, наскільки добре ви знаєте, що робите.
Створіть таблицю та вставте кілька рядків:
create table penguins(foo int, bar varchar(15), baz datetime);
insert into penguins values(1, 'skipper', now());
insert into penguins values(1, 'skipper', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(4, 'rico', now());
select * from penguins;
+------+----------+---------------------+
| foo | bar | baz |
+------+----------+---------------------+
| 1 | skipper | 2014-08-25 14:21:54 |
| 1 | skipper | 2014-08-25 14:21:59 |
| 3 | kowalski | 2014-08-25 14:22:09 |
| 3 | kowalski | 2014-08-25 14:22:13 |
| 3 | kowalski | 2014-08-25 14:22:15 |
| 4 | rico | 2014-08-25 14:22:22 |
+------+----------+---------------------+
6 rows in set (0.00 sec)
Видаліть дублікати на місці:
delete a
from penguins a
left join(
select max(baz) maxtimestamp, foo, bar
from penguins
group by foo, bar) b
on a.baz = maxtimestamp and
a.foo = b.foo and
a.bar = b.bar
where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
select * from penguins;
+------+----------+---------------------+
| foo | bar | baz |
+------+----------+---------------------+
| 1 | skipper | 2014-08-25 14:21:59 |
| 3 | kowalski | 2014-08-25 14:22:15 |
| 4 | rico | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)
Ви закінчили, копії рядків видаляються, зберігається останній часовий маркер.
У вас немає timestamp
або унікальний стовпчик індексів для сортування? Ти живеш у стані виродження. Вам доведеться зробити додаткові кроки, щоб видалити повторювані рядки.
створити таблицю пінгвінів і додати кілька рядків
create table penguins(foo int, bar varchar(15));
insert into penguins values(1, 'skipper');
insert into penguins values(1, 'skipper');
insert into penguins values(3, 'kowalski');
insert into penguins values(3, 'kowalski');
insert into penguins values(3, 'kowalski');
insert into penguins values(4, 'rico');
select * from penguins;
# +------+----------+
# | foo | bar |
# +------+----------+
# | 1 | skipper |
# | 1 | skipper |
# | 3 | kowalski |
# | 3 | kowalski |
# | 3 | kowalski |
# | 4 | rico |
# +------+----------+
зробіть клон першої таблиці та скопіюйте її.
drop table if exists penguins_copy;
create table penguins_copy as ( SELECT foo, bar FROM penguins );
#add an autoincrementing primary key:
ALTER TABLE penguins_copy ADD moo int AUTO_INCREMENT PRIMARY KEY first;
select * from penguins_copy;
# +-----+------+----------+
# | moo | foo | bar |
# +-----+------+----------+
# | 1 | 1 | skipper |
# | 2 | 1 | skipper |
# | 3 | 3 | kowalski |
# | 4 | 3 | kowalski |
# | 5 | 3 | kowalski |
# | 6 | 4 | rico |
# +-----+------+----------+
Максимальний агрегат працює на новому індексі му:
delete a from penguins_copy a left join(
select max(moo) myindex, foo, bar
from penguins_copy
group by foo, bar) b
on a.moo = b.myindex and
a.foo = b.foo and
a.bar = b.bar
where b.myindex IS NULL;
#drop the extra column on the copied table
alter table penguins_copy drop moo;
select * from penguins_copy;
#drop the first table and put the copy table back:
drop table penguins;
create table penguins select * from penguins_copy;
спостерігати та чистити
drop table penguins_copy;
select * from penguins;
+------+----------+
| foo | bar |
+------+----------+
| 1 | skipper |
| 3 | kowalski |
| 4 | rico |
+------+----------+
Elapsed: 1458.359 milliseconds
Що робить цей великий оператор видалення SQL?
Настільні пінгвіни з псевдонімом "a" залишаються об'єднаними на підмножині настільних пінгвінів, що називаються псевдонімом "b". У правій таблиці «b», яка є підмножиною, знаходяться максимальні часові позначки [або max moo], згруповані за колонами foo та bar. Це відповідає лівій таблиці "a". (foo, bar, baz) зліва має кожен рядок таблиці. Права підмножина 'b' має (maxtimestamp, foo, bar), яка відповідає лівій лише тій, що IS max.
Кожен рядок, який не є таким, має значення maxxtimetamp NULL. Відфільтруйте ці рядки NULL, і у вас є набір усіх рядків, згрупованих по футу та смузі, що не є останнім базовим позначенням часових позначок. Видаліть ці.
Зробіть резервну копію таблиці, перш ніж це запустити.
Не дозволяйте цій проблемі повторюватися на цій таблиці:
Якщо ви змусили це працювати, і він випустив ваш "повторюваний рядок" пожежі. Чудово. Тепер визначте новий складний унікальний ключ на вашій таблиці (у цих двох стовпцях), щоб унеможливити додавання більше дублікатів.
Як і хороша імунна система, погані ряди навіть не слід пускати до столу під час вставки. Пізніше всі ці програми, що додають дублікати, будуть висловлювати свій протест, і коли ви їх виправите, ця проблема ніколи не з’явиться знову.
ID
стовпець з автоматичним збільшенням, тоді цей ON
пункт повинен відповідати лише ID
стовпцю, нічого іншого.
Після того, як я сам наткнувся на це питання, на величезній базі даних я не був повністю вражений виконанням жодної з інших відповідей. Я хочу зберегти лише останній повторюваний рядок, а решту видалити.
У одному запиті, без темп-таблиці, це найкраще працювало для мене,
DELETE e.*
FROM employee e
WHERE id IN
(SELECT id
FROM (SELECT MIN(id) as id
FROM employee e2
GROUP BY first_name, last_name
HAVING COUNT(*) > 1) x);
Єдине застереження - це те, що мені доводиться запускати запит кілька разів, але навіть маючи це, я виявив, що він працює для мене краще, ніж інші варіанти.
Здається, це завжди працює для мене:
CREATE TABLE NoDupeTable LIKE DupeTable;
INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;
Який зберігає найнижчий ідентифікатор на кожному з опіків та решту записів, що не належать до дупу.
Я також взявся виконувати наступне, щоб після видалення більше не виникало проблем з дуп:
CREATE TABLE NoDupeTable LIKE DupeTable;
Alter table NoDupeTable Add Unique `Unique` (CommonField1,CommonField2);
INSERT IGNORE NoDupeTable SELECT * FROM DupeTable;
Іншими словами, я створюю дублікат першої таблиці, додаю унікальний індекс у полях, які я не хочу дублювати, а потім роблю той, у Insert IGNORE
якого є перевага, що не виходить з ладу, як звичайно, коли Insert
б перший раз він намагався додати дублікат запису на основі двох полів і швидше ігнорує будь-які подібні записи.
Перемістивши fwd, неможливо створити жодних повторюваних записів на основі цих двох полів.
ORDER BY
в , SELECT
щоб бути впевненими , яка запис на насправді робить його більш до NoDupeTable
?
ORDER by ID Asc
не могло зашкодити, тому я все-таки редагую свою відповідь.
Select Max(ID)
а потім, Order by Max(ID)
але все, що буде зроблено, це змінити порядок вставки. Для отримання найвищого ідентифікатора знадобиться, я вважаю, що більш складний вибір приєднається як, незалежно від того, як ви замовляєте вище, ви будете захоплювати значення поля з нижнього ідентифікатора.
MAX(ID)
або MIN(ID)
й імена стовпців замість *
в SELECT FROM DupeTable
Хоча, в іншому випадку ви просто отримаєте один з ID
«S випадковим чином . Насправді багато SQL і навіть строгий MySQL вимагають викликати сукупну функцію в кожному стовпчику, не вказаному в GROUP BY
пункті.
ID,First,Last,Notes
і записами, 1,Bob,Smith,NULL
а 2,Bob,Smith,Arrears
потім виконання SELECT *Max(ID), First,Last,Notes FROM DupeTable group by First,Last
абеднів, обидва повертають один і той же запис 1, за винятком іншого ідентифікатора. Max (ID) повернеться, 2,Bob,Smith,NULL
а Min (ID) повернеться 1,Bob,Smith,NULL
. Я вважаю, що для отримання другого запису із заборгованістю у примітках потрібен приєднання
Ось проста відповідь:
delete a from target_table a left JOIN (select max(id_field) as id, field_being_repeated
from target_table GROUP BY field_being_repeated) b
on a.field_being_repeated = b.field_being_repeated
and a.id_field = b.id_field
where b.id_field is null;
and a.id_field = b.id
LEFT JOIN
До b
тільки потрібно порівняти b.id
= a.id_field
припускаючи field_id
унікальну автоматичне збільшення ID. так a.field_being_repeated = b.field_being_repeated
це і стороннє. (також b.id_field
у цьому запиті не існує b.id
.
delete p from
product p
inner join (
select max(id) as id, url from product
group by url
having count(*) > 1
) unik on unik.url = p.url and unik.id != p.id;
Я вважаю, що рішення Вернера вище є найзручнішим, оскільки воно працює незалежно від наявності первинного ключа, не псується з таблицями, використовує непрозорі майбутні sql, дуже зрозуміло.
Як я зазначив у своєму коментарі, це рішення не було належним чином пояснено. Отже, це моє, виходячи з цього.
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;
Я пропоную вам зберегти додане обмеження, щоб уникнути нових дублікатів у майбутньому.
Ця процедура видалить усі дублікати (включаючи кратні) у таблиці, зберігаючи останній дублікат. Це розширення Отримати останній запис у кожній групі
Сподіваюся, це комусь корисно.
DROP TABLE IF EXISTS UniqueIDs;
CREATE Temporary table UniqueIDs (id Int(11));
INSERT INTO UniqueIDs
(SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON
(T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields
AND T1.ID < T2.ID)
WHERE T2.ID IS NULL);
DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);
Ще один простий спосіб ... за допомогою UPDATE IGNORE:
Ви повинні використовувати індекс на одному або декількох стовпцях (тип індексу). Створіть новий тимчасовий довідковий стовпчик (не частина індексу). У цьому стовпці ви позначаєте unique, оновляючи його за допомогою ігнорування. Крок за кроком:
Додайте тимчасовий довідковий стовпчик для позначення унікальних даних:
ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;
=> це додасть стовпець у вашу таблицю.
Оновіть таблицю, спробуйте позначити все як унікальне, але ігноруйте можливі помилки через дублювання ключових проблем (записи будуть пропущені):
UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;
=> ви знайдете, що ваші дублікати записів не будуть позначені як унікальні = 'Так', іншими словами лише один з кожного набору дублікатів записів буде позначений як унікальний.
Видаліть усе, що не є унікальним:
DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';
=> Це видалить усі повторювані записи.
Перемістіть стовпець ...
ALTER TABLE `yourtable` DROP `unique`;
unique
стовпець ПОВИНЕН бути доданий до унікального обмеження разом із стовпцями, які в даний час дублюються, інакше вся справа не працює, тому що SET unique
= 'Так' ніколи не вийде з ладу.
unique
це ключове слово mysql. Отже, у неї повинні бути задні підказки (як уже правильно відображено). Використання іншого слова для стовпця може бути зручнішим.
Видалення дублікатів у таблицях MySQL є поширеною проблемою, яка зазвичай відповідає конкретним потребам. Якщо когось цікавить, тут ( Видаліть повторювані рядки в MySQL ) я пояснюю, як використовувати тимчасову таблицю для видалення дублікатів MySQL надійним і швидким способом, також дійсним для обробки великих джерел даних (із прикладами для різних випадків використання).
Алі , у вашому випадку ви можете запустити щось подібне:
-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;
-- add a unique constraint
ALTER TABLE tmp_table1 ADD UNIQUE(sid, title);
-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;
-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;
Відповідь Love @ eric, але, здається, не працює, якщо у вас дійсно великий стіл (я отримую, The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay
коли я намагаюся запустити його). Тож я обмежив запит на приєднання лише для розгляду повторюваних рядків і закінчив:
DELETE a FROM penguins a
LEFT JOIN (SELECT COUNT(baz) AS num, MIN(baz) AS keepBaz, foo
FROM penguins
GROUP BY deviceId HAVING num > 1) b
ON a.baz != b.keepBaz
AND a.foo = b.foo
WHERE b.foo IS NOT NULL
Пункт WHERE в цьому випадку дозволяє MySQL ігнорувати будь-яку рядок, який не має дубліката, а також буде ігнорувати, якщо це перший екземпляр дубліката, тому ігноруються лише наступні дублікати. Змініть, MIN(baz)
щоб MAX(baz)
зберегти останній екземпляр замість першого.
Це працює для великих таблиць:
CREATE Temporary table duplicates AS select max(id) as id, url from links group by url having count(*) > 1;
DELETE l from links l inner join duplicates ld on ld.id = l.id WHERE ld.id IS NOT NULL;
Щоб видалити найдавнішу зміну max(id)
наmin(id)
Це зробить стовпець column_name
первинним ключем, а тим часом ігнорує всі помилки. Таким чином, він видалить рядки з повторюваним значенням для column_name
.
ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);
Я думаю, що це спрацює, в основному скопіювавши таблицю та випорожнивши її, потім вклавши в неї лише окремі значення, але, будь ласка, перевірте це, перш ніж робити це на великих обсягах даних.
Створює копію вашої таблиці
створити таблицю temp_table на зразок oldtablename; вставити temp_table select * зі старого імені;
Порожній ваш оригінальний стіл
ВИДАЛИТИ * від старого імені;
Копіює всі окремі значення з скопійованої таблиці назад у початкову таблицю
ВСТАВИТИ oldtablename SELECT * з групи temp_table за іменем, прізвищем, dob
Видаляє таблицю темп.
Таблиця викидання temp_table
Вам потрібно згрупуватися за полями aLL, які ви хочете виділити.
DELETE T2
FROM table_name T1
JOIN same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)
ось як я зазвичай усуваю дублікати
Ви можете просто використовувати пункт DISTINCT, щоб вибрати список "очищений" (і ось дуже простий приклад того, як це зробити).
DISTINCT
ви втрачаєте будь-яку інформацію про дублікати, яка, можливо, у вас була в першу чергу. Чи можете ви показати спосіб видалення дублікатів за допомогою нього?
Чи може це працювати, якщо ви порахуєте їх, а потім додасте обмеження до запиту на видалення, залишивши лише один?
Наприклад, якщо у вас є дві або більше, напишіть свій запит так:
DELETE FROM table WHERE SID = 1 LIMIT 1;
Для видалення дублікатів даних із таблиці є лише кілька основних кроків:
Ось повний підручник: https://blog.teamsql.io/deleting-duplicate-data-3541485b3473