Sql 删除除一条重复记录外的所有记录
我有一个表,用来跟踪给定配置文件的访问者(用户id到用户id对)。事实证明,我的SQL查询有点不正确,正在生成多个对,而不是预期的单个对。事后看来,我应该在每个id+id对上实施一个唯一的约束 现在,我该怎么收拾桌子呢?我想做的是删除所有重复的对,只留下一个 例如,改变这一点: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
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,则可以手动删除保留一个条目的重复行,只需执行以下步骤:
希望这个解决方案对你有用 请问桌子的结构是什么?是否有第三列用于连接断开值?@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