Sql 删除除一条重复记录外的所有记录

Sql 删除除一条重复记录外的所有记录,sql,sql-delete,Sql,Sql Delete,我有一个表,用来跟踪给定配置文件的访问者(用户id到用户id对)。事实证明,我的SQL查询有点不正确,正在生成多个对,而不是预期的单个对。事后看来,我应该在每个id+id对上实施一个唯一的约束 现在,我该怎么收拾桌子呢?我想做的是删除所有重复的对,只留下一个 例如,改变这一点: 23515 -> 52525 date_visited 23515 -> 52525 date_visited 23515 -> 52525 date_visited 12345 -> 54321

我有一个表,用来跟踪给定配置文件的访问者(用户id到用户id对)。事实证明,我的SQL查询有点不正确,正在生成多个对,而不是预期的单个对。事后看来,我应该在每个id+id对上实施一个唯一的约束

现在,我该怎么收拾桌子呢?我想做的是删除所有重复的对,只留下一个

例如,改变这一点:

23515 -> 52525 date_visited
23515 -> 52525 date_visited
23515 -> 52525 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
12345 -> 54321 date_visited
23515 -> 52525 date_visited
...
为此:

23515 -> 52525 date_visited
12345 -> 54321 date_visited
更新:以下是要求的表格结构:

id  int(10)         UNSIGNED    Non     Aucun   AUTO_INCREMENT
profile_id  int(10)         UNSIGNED    Non     0 
visitor_id  int(10)         UNSIGNED    Non     0
date_visited    timestamp           Non     CURRENT_TIMESTAMP   

ANSI SQL解决方案

在子查询中使用分组依据:

delete from my_tab where id not in 
(select min(id) from my_tab group by profile_id, visitor_id);
您需要某种唯一标识符(这里,我使用的是id)

MySQL解决方案

正如@JamesPoulson所指出的,这会导致MySQL中出现语法错误;正确的解决方案是(如所示):


选择所有唯一的行
将它们复制到新的临时表中
截断原始表
将临时表数据复制到原始表

那就是我要做的。我不确定是否有一个查询可以为您完成所有这些工作。

这里有一个小的解决方案,利用临时表允许他的解决方案在MySQL上工作:

delete from `my_tab` where id not in
( SELECT * FROM 
    (select min(id) from `my_tab` group by profile_id, visitor_id) AS temp_tab
)
这将有助于:

With NewCTE
AS
(
Select *, Row_number() over(partition by ID order by ID)as RowNumber from 
table_name
)
Delete from NewCTE where RowNumber > 1

如果您使用的是SQL,则可以手动删除保留一个条目的重复行,只需执行以下步骤:

  • 进入有重复数据的表
  • 应用筛选器以隔离每个id的重复数据
  • 选择要删除的所有行
  • 按delete并保存结果
  • 对每个具有重复条目的id重复此过程
  • 这是一个漫长的过程,但您可以立即实时看到结果


    希望这个解决方案对你有用

    请问桌子的结构是什么?是否有第三列用于连接断开值?@gbn:已添加表结构(MySQL)。第三列记录用户上次访问配置文件的时间。该结构可能应该通过对profile_id和visitor_id的约束进行修改。P.S:我现在没有SQL填充表,但它是类似于
    if exists update timestamp if not create record
    。很好的解决方案。我没有想到使用一组(经验>知识)。这将显示一个
    无法在FROM子句中指定目标,但有一个解决方法(请参见我的答案)。注意,这在MySQL中不起作用,因为它不允许您修改在内部select:
    错误代码:1093中使用的表。不能在FROM子句中指定更新的目标表“my_tab”
    我已更新了答案;我原本以为人们会阅读@JamesPoulson的评论/答案并使用他们的版本,但显然,情况并非总是如此。如果没有id密钥呢?非常优雅的解决方案。有时最好使用MAX而不是MIN,这样您就可以保留最新版本的行,这些行可能是最正确的。使用临时表是一种很好的反射,实际上是必要的。如果有大量数据,这可能是一种更适合的方法。@FrankSchmitt很好:)如果您的表中没有唯一标识符,并且不想创建临时表,那么这个答案是最好的。许多使用这些答案的人正在处理数百万(甚至数十亿)行。他们需要几个星期才能手工完成这项工作。到底是什么
    With NewCTE
    AS
    (
    Select *, Row_number() over(partition by ID order by ID)as RowNumber from 
    table_name
    )
    Delete from NewCTE where RowNumber > 1