首先,你的查詢會更簡單,速度更快,如果你能在這樣的,你並不需要一個複雜的子查詢配對行的方式對數據進行排序。由於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