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

Stored procedures 删除MySQL表中除5个最新条目外的所有条目,stored-procedures,mysql,Stored Procedures,Mysql,我目前有PHP代码来处理这个逻辑,因为我不知道如何在SQL中处理它。我想创建一个存储过程,该过程将删除除给定配置id的5行之外的所有行。IE config_id=5将被传递给SP,以便它知道要清理的配置id CREATE TABLE `TAA`.`RunHistory` ( `id` int(11) NOT NULL auto_increment, `start_time` datetime default NULL, `stop_time` datetime default NU

我目前有PHP代码来处理这个逻辑,因为我不知道如何在SQL中处理它。我想创建一个存储过程,该过程将删除除给定配置id的5行之外的所有行。IE config_id=5将被传递给SP,以便它知道要清理的配置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;
最新时间将由开始时间确定,如果停止时间为空,但不是最新时间,则应将其删除(如果运行被意外终止,则停止时间可以为空)。

:


下面是我在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
这是一个很好的解决方案。
如果您的表有大量行,则更好。

如何确定“最新”行?基于开始时间?基于停止时间?“基于身份证并不是万无一失的,但这是另一种选择。”托马斯,他根据停车时间说。虽然现在还不清楚该如何处理该字段为空的记录。我很抱歉,我在最初的帖子中被打断了十次,没有重读。起初这是一个提出得很糟糕的问题。@Thomas:最初它说的是停止时间,但我的意思是开始时间,因为停止时间在非常正常的使用下可以为空。可能重复@Luis Melgratti:如果我有一大组ID,语句中的
会比其他方法慢吗?这也表明空停止时间与清理列表无关。@Luis Melgratti:当我运行该查询时,我得到以下错误:
此版本的MySQL还不支持“LIMIT&IN/ALL/ANY/SOME子查询”
MySQL版本=5.0。45@Theo,我的方法简单得多,而且做同样的事情。@Delan,那你怎么删除了你的答案?@manyxcxi那么使用临时表怎么样?因为您正在计划一个存储过程,所以可以创建临时表,将数据插入其中(有序且有限),然后从
运行历史记录
表中删除,而不必担心限制&错误。然后删除临时表。
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;
delete from RunHistory where stop_time is null and id != v_id order by start_time desc limit 5;
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);