Mysql 复杂删除查询
我想删除表中大于30天的所有记录,但保留每个ID最后最年轻的2条记录。 我尝试了极限2和分组,但没有找到解决方案。有人有什么建议吗Mysql 复杂删除查询,mysql,Mysql,我想删除表中大于30天的所有记录,但保留每个ID最后最年轻的2条记录。 我尝试了极限2和分组,但没有找到解决方案。有人有什么建议吗 DROP TABLE IF EXISTS mytable; CREATE TABLE `mytable` ( `timestamp` datetime NOT NULL, `id` int(11) NOT NULL, `data` varchar(100) NOT NULL, PRIMARY KEY (`id`,`timestamp`) );
DROP TABLE IF EXISTS mytable;
CREATE TABLE `mytable` (
`timestamp` datetime NOT NULL,
`id` int(11) NOT NULL,
`data` varchar(100) NOT NULL,
PRIMARY KEY (`id`,`timestamp`)
);
INSERT INTO mytable VALUES
('2014-08-12',22,'data'),
('2014-08-13',22,'data'),
('2014-08-14',22,'data'),
('2014-08-15',22,'data'),
('2014-08-16',54,'data'),
('2014-08-16',22,'data'),
('2014-08-17',54,'data'),
('2014-08-18',54,'data'),
('2014-08-19',54,'data');
Expected Result
2014-08-15,22,data
2014-08-16,22,data
2014-08-18,54,data
2014-08-19,54,data
这就是我目前所拥有的
sql = 'Delete from mytable where timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)';
不正确的解决方案:
希望正确的解决方案:
我不期望它在大数据集上表现良好。尽管它会一直工作,直到日期组不超过组concat\u max\u len。每组取k个条目的想法来自于对的评论。用于处理查询。此数据集不具有适当的代表性,是吗,因为如果您放弃30天规则,您仍然会得到相同的结果!在DB中,日期时间不是日期,因此在数据中,您应该有2014-08-19 12:35:57例如Hi-我只是为了更好的可读性而对日期表示同情选择仅显示id一次-与我相同是的,第一个解决方案是错误的。你能再试试吗?我现在没有mysql来测试我自己。你如何确保删除最早的记录?不知怎的,我错过了一个订单。或者我忽略了什么?不需要订购,因为我只需删除所有超过30天且有2条以上记录的记录。如果按ID显示的记录少于2条,则无论记录有多旧,都不会将其删除。我不确定的部分是从删除的同一个表中选择的。MySQL有时不喜欢这样,你必须找到一种方法,用嵌套的子选择等来愚弄他:是的,这就行了!我更改了查询并删除了SELECT中的第一个:WHERE timestamp
DELETE FROM mytable a
WHERE a.timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)'
AND (a.id, a.timestamp) NOT IN (
SELECT b.id, b.timestamp
FROM mytable b
GROUP BY b.id
ORDER BY b.id, b.timestamp desc
LIMIT 2
)
DELETE FROM mytable a
LEFT JOIN (
SELECT c.id, count(1) as cnt
FROM mytable c
GROUP BY c.id
) b on a.id = b.id
WHERE a.timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)'
AND b.cnt > 2
DELETE t
FROM mytable t
JOIN (
SELECT id, SUBSTRING_INDEX(group_ts, ',', 2) AS two_ts
FROM (
SELECT id, GROUP_CONCAT(timestamp ORDER BY timestamp DESC) AS group_ts
FROM mytable
WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY id
) ag
) tg ON tg.id = t.id AND FIND_IN_SET(t.timestamp, tg.two_ts) = 0
WHERE timestamp < DATE_SUB(NOW(), INTERVAL 30 DAY)