首先,你的查询会更简单,速度更快,如果你能在这样的,你并不需要一个复杂的子查询配对行的方式对数据进行排序。由于MySQL不支持CTE这样做对即时,你需要创建一个临时表:
CREATE TABLE history_ordered (
seq INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
hs_id INT,
mc_id VARCHAR(255),
mc_loggedinuser VARCHAR(255),
hs_time DATETIME,
hs_opcode INT
);
然后,从原始表拉和排序到新表:
INSERT INTO history_ordered (
hs_id, mc_id, mc_loggedinuser,
hs_time, hs_opcode)
SELECT
hs_id, mc_id, mc_loggedinuser,
hs_time, hs_opcode
FROM history ORDER BY mc_id, hs_time;
现在,您可以使用此查询到的数据关联:
SELECT li.mc_id,
li.mc_loggedinuser,
li.hs_time as login_time,
lo.hs_time as logout_time
FROM history_ordered AS li
JOIN history_ordered AS lo
ON lo.seq = li.seq + 1
AND li.hs_opcode = 1;
对于未来的刀片,你可以使用一个触发类似下面,让您的时间表自动更新:
DELIMITER $$
CREATE TRIGGER `match_login` AFTER INSERT ON `history`
FOR EACH ROW
BEGIN
IF NEW.hs_opcode = 2 THEN
DECLARE _user VARCHAR(255);
DECLARE _login DATETIME;
SELECT mc_loggedinuser, hs_time FROM history
WHERE hs_time = (
SELECT MAX(hs_time) FROM history
WHERE hs_opcode = 1
AND mc_id = NEW.mc_id
) INTO _user, _login;
INSERT INTO login_duration
SET machine = NEW.mc_id,
logout = NEW.hs_time,
user = _user,
login = _login;
END IF;
END$$
DELIMITER ;
让我看看我能否更清楚。我有一个名为历史与表mc_id,hs_opcode和hs_time表。对于登录事件,将有唯一的mc_id,hs_opcode = 1,并且hs_time是时间戳。在注销事件上;唯一的mc_id,hs_opcode = 2,而hs_time是时间戳。我需要处理整个表中的每个登录事件并搜索其相应的注销事件。所以对于注销事件,它将是登录事件后该机器的下一个注销记录; mc_id将相等,hs_opcode = 2,时间戳会更大。然后我会将它插入到新表中。 – jomille 2011-12-15 16:45:00
你的问题的答案是否定的,你不应该为此使用游标。事实上,使用游标可能会比下面提出的基于集合的解决方案慢得多。 – 2011-12-15 22:37:59