使用带有日期跨度的表的日期加入表格

时间:2014-07-17 15:52:01

标签: postgresql join postgresql-9.3

我想加入两张桌子。一个是记录表,记录特定时间的事件。另一个是会话表。我想知道在哪个会话中发生了哪个事件。

事件表的timestamp字段类型为timestamp(0) without time zone,会话表的logintimelogouttime类型为timestamp without time zone({{1}这是两个表中都有的字段。)

我试过的SQL是:

userid

当用户注销时,会话就可以了,但当 select S.sessionid from event E left join session S ON S.logintime = ( select MAX(logintime) max from session where ( (logintime < E.timestamp and logouttime > E.timestamp) OR (logintime < E.timestamp AND logouttime is null) ) and S.userid=E.userid ) logouttime时,加入失败,我没有NULL。当我手动执行所有子查询时,它们似乎产生了正确的结果。

后者的例子:

首先,我们采取随机事件记录。

sessionid

其次,我们采用join子句,用接收到的数据填充

select * from event limit 1;
      timestamp      | userid | ....
---------------------+--------+-----
 2014-07-15 15:44:24 |    195 | ....

最后,我们采用与该时间匹配的sessionid。

select MAX(logintime) max from session 
where ((logintime <'2014-07-15 15:44:24' and logouttime > '2014-07-15 15:44:24') OR
       (logintime < '2014-07-15 15:44:24'  AND logouttime is null)) and userid=195;

            max             
----------------------------
 2014-07-15 12:18:03.648875

1 个答案:

答案 0 :(得分:0)

如果您使用的是PostgreSQL 9.2+,则可以使用时间戳范围tsrange来检测containment

select s.sessionid
from event e
left join session s on s.userid = e.userid
  and tsrange(logintime, logouttime) @> E.timestamp

注意:范围可以是unbounded,因此您无需为logouttime IS NULL指定其他案例。

修改:如果一个用户可以在特定时间拥有多个会话(并且您只想选择具有最后一个logintime的会话),则可以使用{{3} }子句:

select distinct on(s.sessionid) s.sessionid
from event e
left join session s on s.userid = e.userid
  and tsrange(logintime, logouttime) @> E.timestamp
order by s.sessionid, logintime desc