我有一个拥有超过7000条记录的数据库。事实证明,这些记录中有几个重复。我找到了一些关于如何删除重复项并且只保留1条记录的建议。 但在我的情况下,事情有点复杂:如果案例与另一条记录保持相同的数据,则不仅仅是重复。相反,几个案例完全可以保持相同的数据。只有当它们保存相同的数据并且都在30秒内插入时,它们才被标记为重复。
因此,我需要一个删除重复项的SQL语句(例如:除<form>
和id
之外的所有字段),如果它们已在40秒范围内插入(例如:评估datetime
} field。。
由于我是除了SQL专家之外的所有人,并且无法在线找到合适的解决方案,我真的希望你们中的一些人可以帮助我并指出我正确的方向。非常感谢!
表结构如下:
datetime
所以,为了再次澄清,重复的案例是:
除了CREATE TABLE IF NOT EXISTS `wp_ttr_results` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`schoolyear` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
`datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`area` varchar(15) CHARACTER SET utf8 NOT NULL,
`content` varchar(10) CHARACTER SET utf8 NOT NULL,
`types` varchar(100) CHARACTER SET utf8 NOT NULL,
`tasksWrong` varchar(300) DEFAULT NULL,
`tasksRight` varchar(300) DEFAULT NULL,
`tasksData` longtext CHARACTER SET utf8,
`parent_id` varchar(20) DEFAULT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=68696 ;
和id
字段之外,[1]包含与所有字段的其他案例相同的数据
[2]根据datetime
字段在数据库中插入,在另一条具有相同值的记录的40秒内
如果满足两个条件,则应删除除一个以外的所有情况。
答案 0 :(得分:3)
正如@Juru在评论中指出的那样,我们需要一个手术刀来削减这个。但是,可以通过存储过程以迭代方式执行此操作。
首先,我们使用自联接来识别每条记录的第一个副本,这本身并不重复:
SELECT DISTINCT
MIN(postdups.id AS id)
FROM wp_ttr_results AS base
INNER JOIN wp_ttr_results AS postdups
ON base.id<postdups.id
AND UNIX_TIMESTAMP(postdups.datetime)-UNIX_TIMESTAMP(base.datetime)<40
AND base.user_id=postdups.user_id
AND base.schoolyear=postdups.schoolyear
AND base.area=postdups.area
AND base.content=postdups.content
AND base.types=postdups.types
AND base.tasksWrong=postdups.tasksWrong
AND base.tasksRight=postdups.tasksRight
AND base.parent_id=postdups.user_id
LEFT JOIN wp_ttr_results AS predups
ON base.id>predups.id
AND UNIX_TIMESTAMP(base.datetime)-UNIX_TIMESTAMP(predups.datetime)<40
AND base.user_id=predups.user_id
AND base.schoolyear=predups.schoolyear
AND base.area=predups.area
AND base.content=predups.content
AND base.types=predups.types
AND base.tasksWrong=predups.tasksWrong
AND base.tasksRight=predups.tasksRight
AND base.parent_id=predups.user_id
WHERE predups.id IS NULL
GROUP BY base.id
;
这将选择所有以后记录(id
)中的最低base.id<postdups.id
,这些记录与现有记录具有相同的有效负载,并且在40秒内(UNIX_TIMESTAMP(dups) .datetime)-UNIX_TIMESTAMP(base.datetime)&lt; 40),但跳过那些本身重复的基本记录。在@Juru的示例中,:30
记录会被点击,因为它是:00
记录的副本,它本身不是重复记录,但:41
记录会不会被点击,因为它只与:30
重复,:00
本身是CREATE TEMPORARY TABLE cleanUpDuplicatesTemp SELECT DISTINCT
-- as above
;
DELETE FROM wp_ttr_results
WHERE id IN
(SELECT id FROM cleanUpDuplicatesTemp)
;
DROP TABLE cleanUpDuplicatesTemp
;
的副本。
我们有
现在我们必须删除此记录 - 因为MySQL无法从正在读取的表中删除,我们必须使用变量来实现:
SELECT DISTINCT
到目前为止,我们将删除每条记录的第一个副本,在此过程中可能会发生变化,这将被视为重复...
最后,我们必须遍历此过程,如果DELIMITER ;;
CREATE PROCEDURE cleanUpDuplicates()
BEGIN
DECLARE numDuplicates INT;
iterate: LOOP
DROP TABLE IF EXISTS cleanUpDuplicatesTemp;
CREATE TEMPORARY TABLE cleanUpDuplicatesTemp
SELECT DISTINCT
MIN(postdups.id AS id)
FROM wp_ttr_results AS base
INNER JOIN wp_ttr_results AS postdups
ON base.id<postdups.id
AND UNIX_TIMESTAMP(postdups.datetime)-UNIX_TIMESTAMP(base.datetime)<40
AND base.user_id=postdups.user_id
AND base.schoolyear=postdups.schoolyear
AND base.area=postdups.area
AND base.content=postdups.content
AND base.types=postdups.types
AND base.tasksWrong=postdups.tasksWrong
AND base.tasksRight=postdups.tasksRight
AND base.parent_id=postdups.user_id
LEFT JOIN wp_ttr_results AS predups
ON base.id>predups.id
AND UNIX_TIMESTAMP(base.datetime)-UNIX_TIMESTAMP(predups.datetime)<40
AND base.user_id=predups.user_id
AND base.schoolyear=predups.schoolyear
AND base.area=predups.area
AND base.content=predups.content
AND base.types=predups.types
AND base.tasksWrong=predups.tasksWrong
AND base.tasksRight=predups.tasksRight
AND base.parent_id=predups.user_id
WHERE predups.id IS NULL
GROUP BY base.id;
SELECT COUNT(*) INTO numDuplicates FROM cleanUpDuplicatesTemp;
IF numDuplicates<=0 THEN
LEAVE iterate;
END IF;
DELETE FROM wp_ttr_results
WHERE id IN
(SELECT id FROM cleanUpDuplicatesTemp)
END LOOP iterate;
DROP TABLE IF EXISTS cleanUpDuplicatesTemp;
END;;
DELIMITER ;
没有返回任何内容,则退出循环。
将所有内容整合到一个存储过程中:
CALL cleanUpDuplicates;
现在一个简单的$database = new mysqli('localhost', 'username', 'password'); #see, no database selected
$query1 = "select * from database1.tableX";
$res1 = $database->query($query1);
$query2 = "select * from database2.tableY";
$res2 = $database->query($query2);
应该可以解决问题。
答案 1 :(得分:0)
这个可能有效,但可能不会很快......
DELETE FROM dupes
USING wp_ttr_results AS dupes
INNER JOIN wp_ttr_results AS origs
ON dupes.field1 = origs.field1
AND dupes.field2 = origs.field2
AND ....
AND AS dupes.id <> origs.id
AND dupes.`datetime` BETWEEN orig.`datetime` AND (orig.`datetime` + INTERVAL 40 SECOND)
;