Mysql 复杂删除查询

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`) );

我想删除表中大于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`)
  );

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 timestampDELETE 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)