删除除一个以外的所有重复项

Mat*_*iby 3 mysql sql

我们有一个表,business_usersuser_idbusiness_id我们有重复.如何编写一个删除所有重复项的查询?

MvG*_*MvG 9

完全相同的行

如果你想避免完全相同的行,我首先理解你的问题,那么你可以选择唯一的行到一个单独的表并从中重新创建表数据.

CREATE TEMPORARY TABLE tmp SELECT DISTINCT * FROM business_users;
DELETE FROM business_users;
INSERT INTO business_users SELECT * FROM tmp;
DROP TABLE tmp;
Run Code Online (Sandbox Code Playgroud)

但是,如果存在引用此表的任何外键约束,请小心,因为临时删除行可能会导致其他位置的级联删除.

引入一个独特的约束

如果您只关心对user_idbusiness_id,您可能希望将来避免引入重复项.您可以将现有数据移动到临时表,添加约束,然后将表数据移回,忽略重复项.

CREATE TEMPORARY TABLE tmp SELECT * FROM business_users;
DELETE FROM business_users;
ALTER TABLE business_users ADD UNIQUE (user_id, business_id);
INSERT IGNORE INTO business_users SELECT * FROM tmp;
DROP TABLE tmp;
Run Code Online (Sandbox Code Playgroud)

以上答案基于这个答案.关于外键的警告就像在上面一节中所做的那样适用.

一次性移除

如果您只想执行单个查询,而不以任何方式修改表结构,并且您有一个id标识每一行的主键,那么您可以尝试以下操作:

DELETE FROM business_users WHERE id NOT IN
    (SELECT MIN(id) FROM business_users GROUP BY user_id, business_id);
Run Code Online (Sandbox Code Playgroud)

此答案之前提出了类似的想法.

如果上述请求失败,因为您不允许在同一步骤中从表中读取和删除,则可以再次使用临时表:

CREATE TEMPORARY TABLE tmp
SELECT MIN(id) id FROM business_users GROUP BY user_id, business_id;
DELETE FROM business_users WHERE id NOT IN (SELECT id FROM tmp);
DROP TABLE tmp;
Run Code Online (Sandbox Code Playgroud)

如果您愿意,在以这种方式清理数据后仍然可以引入唯一性约束.为此,请执行ALTER TABLE上一节中的行.

  • @Pete:第二个中的“ MIN(id)id”是“ MIN(id)AS id”的缩写:它指定列的名称,因此结果表中的列实际上没有命名为“ MIN” (id)`,这将非常令人困惑且难以键入。在第一个查询中,列的名称无关紧要,因为子查询仅用作集合。 (2认同)