まずあなたが行をペアリングするために複雑な副問合せを必要としないような方法でデータを注文することができれば、あなたのクエリが単純(かつ迅速)になります。
:新しいテーブルに元のテーブルから引き出し、並べ替え、その後
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
);
:MySQLはオンザフライでこれを行うには、CTEをサポートしていませんので、あなたは一時テーブルを作成する必要がありますあなたは今のデータを相関させるために、このクエリを使用することができます
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を持つHistoryというテーブルを持っています。ログインイベントの場合は、一意のmc_id、hs_opcode = 1、hs_timeがタイムスタンプです。ログアウトイベント。一意のmc_id、hs_opcode = 2、hs_timeはタイムスタンプです。私はテーブル全体で各ログインイベントを処理し、対応するログアウトイベントを検索する必要があります。したがって、ログアウトイベントの場合は、ログインイベント後のそのマシンの次のログアウトレコードになります。 mc_idは等しく、hs_opcode = 2になり、タイムスタンプは大きくなります。それから私はこれを新しいテーブルに挿入します。 – jomille
あなたの質問に対する答えはいいえです。これにはカーソルを使う必要はありません。実際には、カーソルの使用は、以下で提案するセットベースのソリューションよりもはるかに遅くなる可能性があります。 –