删除MySQL表中除5个最新条目外的所有条目

时间:2010-04-28 16:16:33

标签: stored-procedures mysql

我目前有PHP代码处理这个逻辑,因为我不知道如何在SQL中处理它。我想创建一个存储过程,删除除给定config_id的最新行之外的所有行。 IE config_id = 5传递给SP,因此它知道它要清理哪个config_id。

CREATE TABLE  `TAA`.`RunHistory` (
  `id` int(11) NOT NULL auto_increment,
  `start_time` datetime default NULL,
  `stop_time` datetime default NULL,
  `success_lines` int(11) default NULL,
  `error_lines` int(11) default NULL,
  `config_id` int(11) NOT NULL,
  `file_id` int(11) NOT NULL,
  `notes` text NOT NULL,
  `log_file` longblob,
  `save` tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8;

最新将由start_time确定,如果stop_time为null但不是最新的应删除(如果运行被毫不客气地杀死,则stop_time可以为null)。

4 个答案:

答案 0 :(得分:12)

SQL query: Delete all records from the table except latest N?

DELETE FROM `runHistory`
WHERE id NOT IN (
  SELECT id
  FROM (
    SELECT id
    FROM `runHistory`
    ORDER BY start_time DESC
    LIMIT 5 
  ) foo
);

答案 1 :(得分:1)

这是我在MySQL 5.1.46上测试过的一个过程,但是它没有使用子查询,所以你不会在子查询中得到关于不支持LIMIT的错误。

CREATE PROCEDURE DeleteBut5(IN c INT) BEGIN
  DECLARE i INT;
  DECLARE s DATETIME;

  SELECT id, stop_time INTO i, s
  FROM RunHistory WHERE config_id = c
  ORDER BY stop_time DESC, id DESC
  LIMIT 4, 1;

  DELETE FROM RunHistory WHERE stop_time < s OR stop_time = s AND id < i;
END

我建议您创建此覆盖索引:

CREATE INDEX cov ON RunHistory (config_id, stop_time, id);

答案 2 :(得分:0)

begin;
declare v_start_time datetime;
declare v_id int;
#Find the id of the newest run
select id into v_id from RunHistory where start_time = (select max(start_time) from RunHistory);
#delete null stop times except for the newest run
delete from RunHistory where stop_time is null and id != v_id;
#first row is 0... skip 0-4, show 5
select start_time into v_start_time from RunHistory order by stop_time desc limit 4,1;
delete from RunHistory where start_time < v_start_time;
end;

你去吧。我建议索引start_time。 Stop_time可能值得也可能不值得索引。可能不是。您可以通过将删除语句更改为以下内容来优化该语句,因为我们将删除前五个之后的任何内容:

delete from RunHistory where stop_time is null and id != v_id order by start_time desc limit 5;

答案 3 :(得分:0)

https://stackoverflow.com/a/8303440/2576076是一个很好的解决方案。 如果你的桌子有很多行,那就更好了。