如何删除MySQL表上的重复项?
我需要删除mysql表上指定sid的重复行。
我怎样才能做到这一点与SQL查询?
DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"
这样的事情,但我不知道该怎么做。
这将删除重复的地方,而不是一个新的表
ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)
注意:只有索引适合内存才能正常工作
假设你有一个表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
在删除所有SID-s的重复项之后,不仅仅是单一的。
用临时表
CREATE TABLE table_temp AS SELECT * FROM table GROUP BY title, SID; DROP TABLE table; RENAME TABLE table_temp TO table;
由于temp_table
是新创build的,它没有索引。 删除重复项之后,您需要重新创build它们。 您可以使用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 )
在MySQL中删除重复的行,演练
创build表格并插入一些行:
dev-db> create table penguins(foo int, bar varchar(15), baz datetime); Query OK, 0 rows affected (0.07 sec) dev-db> insert into penguins values(1, 'skipper', now()); dev-db> insert into penguins values(1, 'skipper', now()); dev-db> insert into penguins values(3, 'kowalski', now()); dev-db> insert into penguins values(3, 'kowalski', now()); dev-db> insert into penguins values(3, 'kowalski', now()); dev-db> insert into penguins values(4, 'rico', now()); Query OK, 6 rows affected (0.07 sec) dev-db> 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)
然后删除重复项:
dev-db> 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)
结果:
dev-db> 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)
那是什么删除语句呢
伪代码:按两列删除重复的行。 使用最大聚合来select每个组的一行。 左连接返回左表中的所有行,右表中的匹配行返回。 在这种情况下,左表具有表中的所有行,右侧仅包含那些为NULL的行(而不是每个组要保留的行)。 删除这些行,每个组只剩下唯一的一行。
更多的技术说明,你应该如何阅读sql删除语句:
带有别名“a”的表企鹅被加在一个名为别名“b”的企鹅桌子上。 作为子集的右手表“b”查找由foo和bar分组的最大时间戳。 这与左手表“a”相匹配。 (foo,bar,baz)在表格的每一行都有。 右边的子集“b”有一个(maxtimestamp,foo,bar),它只与最左边的那个相匹配。
每个不是最大值的行的值都是NULL的maxtimestamp。 在这些NULL行上过滤,并且你有一组由foo和bar分组的所有行,这不是最新的时间戳baz。 删除那些。
在执行此操作之前先备份表格。
防止这个问题再次发生在这张桌子上:
如果你有这个工作,并把你的“重复行”火。 大。 你的工作还没有完成。 在你的表(在这两列)上定义一个新的复合唯一键,以防止首先添加更多的重复项。 就像一个好的免疫系统一样,在插入的时候甚至不允许坏的行进入桌子。 后来所有这些添加重复的程序都会播出他们的抗议,当你修复它们时,这个问题再也不会出现。
这似乎总是为我工作:
CREATE TABLE NoDupeTable LIKE DupeTable; INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;
其中保留每个愚蠢的最低的身份证和其他非愚蠢的logging。
这是一个简单的答案:
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;
DELETE FROM table WHERE Field IN (SELECT Field FROM table GROUP BY Field HAVING COUNT(Field) > 1) WHERE SID = "1"
编辑:
上面的查询将删除所有重复的logging,以保持每一个:
DELETE FROM table WHERE id NOT IN (SELECT id FROM (SELECT id, field FROM table WHERE SID = "1" GROUP BY field HAVING COUNT(field) > 1) as tmp) AND field in (SELECT DISTINCT field FROM table WHERE SID = "1" GROUP BY field HAVING COUNT(field) > 1)
我不能完全testing它,但我认为这工作。
此过程将删除表中的所有重复项(包括倍数),保留最后的重复项。 这是检索每个组中最后一条logging的扩展
希望这对某人有用。
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);
在自己遇到这个问题之后,在一个庞大的数据库上,我对其他任何答案的performance都不甚满意。 我只想保留最新的重复行,并删除其余的。
在一个查询语句中,没有临时表,这对我来说是最好的,
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);
唯一需要注意的是我必须多次运行查询,但即使如此,我发现它比其他选项更适合我。
这个工作为我删除旧logging:
delete from table where id in (select min(e.id) from (select * from table) e group by column1, column2 having count(*) > 1 );
您可以将min(e.id)replace为max(e.id)以删除最新的logging。
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;
delete from `table` where `table`.`SID` in ( select t.SID from table t join table t1 on t.title = t1.title where t.SID > t1.SID )
爱@ 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`);
另一个简单的方法…使用UPDATE IGNORE:
你必须使用一个或多个列索引(types索引)。 创build一个新的临时引用列(不是索引的一部分)。 在本专栏中,您通过使用ignore子句进行更新来标记唯一标识。 一步步:
添加临时参考列以标记唯一身份validation:
ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;
=>这将在你的表中添加一列。
更新表格,尝试将所有内容标记为唯一,但忽略由于重复键入问题而导致的可能错误(logging将被跳过):
UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;
=>您会发现您的重复logging不会被标记为唯一=“是”,换句话说,每组重复logging中只有一个会被标记为唯一。
删除所有不是唯一的东西:
DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';
=>这将删除所有重复logging。
放下列…
ALTER TABLE `yourtable` DROP `unique`;
你可以使用DISTINCT子句来select“清理”列表( 这里是一个非常简单的例子)。
如果你计算它们,它可以工作,然后添加一个限制删除查询只留下一个?
例如,如果您有两个或更多,请编写如下所示的查询:
DELETE FROM table WHERE SID = 1 LIMIT 1;
从表格中删除重复的数据只需要几个基本步骤:
- 备份你的桌子!
- find重复的行
- 删除重复的行
这里是完整的教程: https : //blog.teamsql.io/deleting-duplicate-data-3541485b3473