2

我有一个问题,实际上是一个关于如何根据第一个 SELECT 的名称和时间戳删除 MySQL 表中所有重复项的最简单方法的问题。

所以,我有这张桌子:

SELECT * FROM search;
+------+--------+------------+--------------------------+-----------------------+
|  id  |  uid   |   string   |           cat            |         timestamp     | 
+------+--------+------------+--------------------------+-----------------------+
|39523 |   87   |eat to live |  a:1:{i:0;s:5:"toate";}  |  2013-10-07 17:01:41  |
|39524 |   87   |eat to live |  s:6:"author";           |  2013-10-07 17:01:41  |
|39525 |   87   |eat to live |  s:6:"people";           |  2013-10-07 17:01:41  |
|39526 |   87   |eat to live |  s:7:"company";          |  2013-10-07 17:01:41  |
|39527 |   87   |eat to live |  s:6:"author";           |  2013-10-07 17:01:42  |
|39532 |   31   |  friends   |  a:1:{i:0;s:5:"toate";}  |  2013-10-07 17:04:17  |
|39533 |   31   |  friends   |  s:6:"people";           |  2013-10-07 17:04:17  |
|39534 |   31   |  friends   |  s:7:"company";          |  2013-10-07 17:04:17  |
|39535 |   31   |  friends   |  s:6:"author";           |  2013-10-07 17:04:17  |
+------+--------+------------+--------------------------+-----------------------+

我只想留下第一个独特的外观。我的解决方案是选择所有行,遍历它们,并为每一行删除与相同字符串匹配的所有行,相同的 uid 和时间戳是相同的时间戳或 +1 秒。

有什么想法/建议吗?我可以在 PHP 中执行此操作,并且想知道是否有更简单的方法可以直接使用 SQL 查询执行此操作。

谢谢

4

2 回答 2

3

MySQL 支持多表 DELETE,因此您可以进行自连接,这样只有具有更大 id 的行才会包含在删除中。

DELETE s2
FROM search AS s1 JOIN search AS s2 
  ON s1.string = s2.string AND s1.uid = s2.uid AND s1.id < s2.id;

如果您想向联接添加一些逻辑,以便仅在匹配s2行与第一行相距不超过 1 秒时才删除,您也可以这样做:

DELETE s2
FROM search AS s1 JOIN search AS s2 
  ON s1.string = s2.string AND s1.uid = s2.uid AND s1.id < s2.id;
    AND s2.timestamp <= s1.timestamp+1

但是,如果您在一行中有许多相隔 1 秒的条目,这将删除除第一个之外的所有条目。我不确定在这种情况下你想做什么。

于 2013-10-07T16:30:05.827 回答
0

您可以使用此代码删除,基于重复的是具有相同uidstring的那个;这段代码将只留下第一次出现。

DELETE FROM search 
WHERE id NOT IN 
(SELECT MIN(id) FROM search GROUP BY uid, string);
于 2013-10-07T16:29:03.510 回答