mysql - 我应该在 SQL 过程中使用游标吗?

标签 mysql cursor

我有一个包含计算机登录和注销事件的表。每行都是一个单独的事件,带有时间戳、机器名称、登录或注销事件代码和其他详细信息。我需要创建一个 SQL 过程来遍历此表并找到相应的登录和注销事件,并将新行插入到另一个包含机器名称、登录时间、注销时间和持续时间的表中。

那么,我应该使用游标来执行此操作还是有更好的方法来执行此操作?数据库非常庞大,因此效率肯定是一个问题。任何建议的伪代码也会很棒。

[编辑:摘自评论]

源表:

History (
      mc_id
    , hs_opcode
    , hs_time
)

现有数据解读:

Login_Event  = unique mc_id, hs_opcode = 1, and hs_time is the timestamp
Logout_Event = unique mc_id, hs_opcode = 2, and hs_time is the timestamp

最佳答案

首先,如果您可以按照不需要复杂子查询来配对行的方式对数据进行排序,那么您的查询将会更简单(也更快)。由于 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;

对于 future 的插入,您可以使用如下触发器来自动更新持续时间表:

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 ;

关于mysql - 我应该在 SQL 过程中使用游标吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8523183/

相关文章:

mysql - 将不同记录从一个表复制到另一个表的游标

delphi - 将 Delphi 转换为 Borland C++ 构建器

mysql - CALL 上的存储过程错误

MySQL - GROUP BY 的多个条件及其结果

java - 返回类型的计数或最大值计数可以返回mysql

mysql - 按特定元素连接、过滤并返回补充记录的 SQL 查询

Android数据库多选

android - 使用游标和 SimpleCursorAdapter 更新 ListView

java - Quartz - 重启调度器

PHP ini 显示错误