【问题标题】:Join a table with dates with a table with date spans将带有日期的表格与带有日期跨度的表格连接起来
【发布时间】:2023-04-04 19:27:03
【问题描述】:

我有两个要加入的表。一个是记录特定时间事件的日志表。另一个是会话表。我想知道哪个事件发生在哪个会话中。

事件表具有timestamp(0) without time zone 类型的timestamp 字段,会话表具有timestamp without time zone 类型的logintimelogouttimeuserid 是两个表中都可用的字段) .

我试过的SQL是这样的:

 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
 )

当用户注销时,会话正常,但是当logouttimeNULL 时,加入失败并且我没有得到sessionid。当我手动执行所有子查询时,它们似乎会产生正确的结果。

后者的例子:

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

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

其次,我们取join子句,填写接收到的数据

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

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

select * from session where logintime='2014-07-15 12:18:03.648875';
              sessionid               | userid |         logintime          | logouttime 
--------------------------------------+--------+----------------------------+------------
 4e56b28a-0c09-11e4-af0d-5b9f3f52ff0d |    195 | 2014-07-15 12:18:03.648875 | 

【问题讨论】:

  • PostgreSQL 版本? (您可以添加为标签)

标签: postgresql join postgresql-9.3


【解决方案1】:

如果你使用的是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 的会话),您可以使用DISTINCT ON 子句:

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

【讨论】:

  • 感谢tsrange,它现在工作得更好,但我过去也加入了“开放”会话(可能有多个开放会话,我需要加入最后一个,因此我的MAX 部分)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
相关资源
最近更新 更多