查询sql“事件日志”架构

时间:2013-02-20 02:52:27

标签: sql postgresql event-log

给定此模式(在postgresql-9.2中):

CREATE TABLE foo (
   id serial PRIMARY KEY,
   ...other columns elided...
);

CREATE TYPE event_type AS ENUM ('start', 'stop');

CREATE TABLE foo_event (
   id serial PRIMARY KEY,
   foo_id integer NOT NULL REFERENCES foo (id),
   timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   type event_type NOT NULL
);

如何让所有“正在运行”foo?也就是说,foo s的最近事件是“开始”,或者甚至更好,foo s至少启动过一次,并且在最后一次之后没有stop s { {1}}(如果我将来添加更多事件类型)。


到目前为止,我最好的尝试是:

start

这里的问题当然是它永远不会返回任何曾被停止过的SELECT * FROM foo WHERE id NOT IN (SELECT foo_id FROM foo_event WHERE type='stop');

1 个答案:

答案 0 :(得分:3)

使用MAX()聚合来检索每个start组的最新foo_id个事件,您可以对检索最新的子查询执行LEFT JOIN(同时{ {1}})MAX()事件大于stop子句中的start事件。在ON事件子查询中查找NULL s的那些,这意味着没有匹配。

stop

看看,它确实有效! http://sqlfiddle.com/#!12/8642d/1

注意,如果停止事件可以与其相应的启动事件同时结束,请在SELECT foo.*, fstart.* FROM foo INNER JOIN ( /* Left side gets most recent start events */ SELECT foo_id, MAX(timestamp) AS start_ts FROM foo_event WHERE event_type = 'start' GROUP BY foo_id ) fstart ON foo.id = fstart.foo_id /* Right side gets most recent stop events */ LEFT JOIN ( SELECT foo_id, MAX(timestamp) AS stop_ts FROM foo_event WHERE event_type = 'stop' GROUP BY foo_id /* JOIN rows that have a greater stop time than start time */ ) fstop ON fstart.foo_id = fstop.foo_id AND fstop.stop_ts > fstart.start_ts /* And find rows where there's no matching stop event greater than the start */ WHERE fstop.stop_ts IS NULL 子句中使用>=而不是> ...

相关问题