3

この質問をコンテキストに入れるために、イベントログに基づいて「アプリ内の時間」を計算しようとしています。

次の表を想定します。

user_id   event_time
2         2012-05-09 07:03:38
3         2012-05-09 07:03:42
4         2012-05-09 07:03:43
2         2012-05-09 07:03:44
2         2012-05-09 07:03:45
4         2012-05-09 07:03:52
2         2012-05-09 07:06:30

event_time互いに2分以内にある(そしてユーザーごとにグループ化された)タイムスタンプのセットから、最高と最低の差を取得したいと思います。タイムスタンプがセットから2分間隔の外にある場合、それは別のセットの一部と見なされる必要があります。

必要な出力:

user_id  seconds_interval
2        7     (because 07:03:45 - 07:03:38 is 7 seconds)
3        0     (because 07:03:42)
4        9     (because 07:03:52 - 2012-05-09 07:03:43)
2        0     (because 07:06:30 is outside 2 min interval of 1st user_id=2 set)

これは私が試したことですが、グループ化することはできませんseconds_interval(できたとしても、これが正しい方向かどうかはわかりません)。

SELECT (max(tr.event_time)-min(tr.event_time)) as seconds_interval
FROM some_table tr
INNER JOIN TrackingRaw tr2 ON (tr.event_time BETWEEN 
   tr2.event_time - INTERVAL 2 MINUTE AND tr2.event_time + INTERVAL 2 MINUTE) 
GROUP BY seconds_interval
4

1 に答える 1

4

既存のテーブルにクエリを実行して必要なデータを生成する非常に簡単な方法はないと思います。ただし、ユーザーセッションの2番目のテーブルを維持することはできます(もちろん、これには、後で別のセッションタイムアウト期間を使用するレポートが必要になった場合に、テーブルを最初から再作成する必要があるという欠点があります)。

CREATE TABLE Sessions (
  user_id INT,
  session_start TIMESTAMP,
  session_end   TIMESTAMP,
  PRIMARY KEY (user_id, session_start),
  FOREIGN KEY (user_id, session_start) REFERENCES TrackingRaw(user_id, event_time),
  FOREIGN KEY (user_id, session_end  ) REFERENCES TrackingRaw(user_id, event_time)
);

次を使用するトリガーを使用して、このようなテーブルに自動的にデータを入力/更新できますINSERT ... SELECT ... ON DUPLICATE KEY UPDATE

CREATE TRIGGER after_insert_TrackingRaw AFTER INSERT ON TrackingRaw FOR EACH ROW
  INSERT INTO Sessions (user_id, session_start, session_end)
    SELECT NEW.user_id,
           IFNULL(MAX(session_start), NEW.event_time),
           NEW.event_time
    FROM   Sessions
    WHERE  user_id = NEW.user_id
       AND session_end >= NEW.event_time - INTERVAL 2 MINUTE
  ON DUPLICATE KEY UPDATE
    session_start = session_start,
    session_end   = NEW.event_time;

次に、目的のクエリ結果を取得するには、次のようにします。

SELECT user_id, session_end - session_start AS seconds_interval FROM Sessions;

sqlfiddleでそれを参照してください。


アップデート

Sessionsさらに熟考した後、もちろん、ストアドプロシージャ内にそのようなテーブルを作成できます。

CREATE PROCEDURE getSessions(IN secs INT) READS SQL DATA BEGIN
  DECLARE no_more_rows BOOLEAN;
  DECLARE cur CURSOR FOR
    SELECT user_id, event_time FROM TrackingRaw ORDER BY event_time ASC;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE;

  DROP   TEMPORARY TABLE IF EXISTS Sessions;
  CREATE TEMPORARY TABLE Sessions (
    user_id INT,
    session_start TIMESTAMP,
    session_end   TIMESTAMP,
    PRIMARY KEY(user_id,session_start),
    FOREIGN KEY(user_id,session_start) REFERENCES TrackingRaw(user_id,event_time),
    FOREIGN KEY(user_id,session_end  ) REFERENCES TrackingRaw(user_id,event_time)
  );

  OPEN cur;
  the_loop: LOOP
    FETCH cur INTO @u, @t;
    IF no_more_rows THEN
      CLOSE cur;
      LEAVE the_loop;
    END IF;

    INSERT INTO Sessions
      SELECT @u, IFNULL(MAX(session_start), @t), @t
      FROM   Sessions
      WHERE  user_id = @u AND session_end >= @t - secs
    ON DUPLICATE KEY UPDATE
      session_start = session_start, session_end = @t
  END LOOP the_loop;

  DEALLOCATE PREPARE stmt;
  SELECT user_id, session_end - session_start AS seconds_interval FROM Sessions;
  DROP TEMPORARY TABLE Sessions;
END;;

そして、出力を取得するには:

CALL getSessions(120); -- for a 2 minute (120 second) timeout
于 2012-06-29T08:46:45.520 に答える