计算并发用户会话的最大数量

我在PostgreSQL 9.6中有一个UserSession表,用于存储用户的登录和注销时间,我想计算并发会话的最大数量-仅当它们重叠至少为时才被认为是并发的30分钟

示例

userid      |  starttime                |  endtime  
------------+---------------------------+--------------------------
1           |  01-Oct-19 6:00:00 AM     |    01-Oct-19 11:10:00 AM  
2           |  01-Oct-19 11:00:00 AM    |    01-Oct-19 4:00:00 PM 
3           |  01-Oct-19 10:30:00 AM    |    01-Oct-19 4:00:00 PM 

在这里,会话1和2不是并发的,因为它们仅重叠10分钟,而会话1和3是并发的,因为它们重叠30分钟以上,所以结果是2个并发会话

注意::仅当所有n个会话都重叠至少30分钟时,结果才是n。

表定义

CREATE TABLE UserSessions (
    SessionID bigserial NOT NULL,UserID bigint NOT NULL,StartTime timestamp NOT NULL,EndTime timestamp NULL,OrganisationID bigint NOT NULL,CONSTRAINT PK_SessionsID PRIMARY KEY(SessionID),CONSTRAINT FK_UserID FOREIGN KEY(UserID) REFERENCES GlobalUsers(UserID),CONSTRAINT FK_OrganisationID FOREIGN KEY(OrganisationID) REFERENCES Organisations(OrganisationID)
);

类似问题

这里有一个类似的问题:Count max number of concurrent user session,但是在同一时间点存在并发方式,对于我来说,我需要检查它们是否至少重叠30分钟

zjd1987zjd 回答:计算并发用户会话的最大数量

从每个时间范围的结束(或开始)减去30分钟。然后基本上按照我的referenced "simple" answer中所述进行操作(在正确的方向进行30分钟的调整)。小于30分钟的范围会被事先消除-这是有道理的,因为它们永远不会成为30分钟连续重叠的一部分。也使查询更快。

计算2019年10月的所有天数(示例范围):

WITH range AS (SELECT timestamp '2019-10-01' AS start_ts  -- incl. lower bound,timestamp '2019-11-01' AS end_ts)   -- excl. upper bound,cte AS (
   SELECT userid,starttime
       -- default to current timestamp if NULL,COALESCE(endtime,localtimestamp) - interval '30 min' AS endtime
   FROM   usersessions,range r
   WHERE  starttime <  r.end_ts  -- count overlaps *starting* in outer time range
   AND   (endtime   >= r.start_ts + interval '30 min' OR endtime IS NULL)

   ),ct AS (
   SELECT ts,sum(ct) OVER (ORDER BY ts,ct) AS session_ct
   FROM  (
      SELECT endtime AS ts,-1 AS ct FROM cte
      UNION ALL
      SELECT starttime,+1       FROM cte
      ) sub
   )
SELECT ts::date,max(session_ct) AS max_concurrent_sessions
FROM   ct,range r
WHERE  ts >= r.start_ts
AND    ts <  r.end_ts            -- crop outer time range
GROUP  BY ts::date
ORDER  BY 1;

db 提琴here

请注意,LOCALTIMESTAMP取决于当前会话的时区。考虑在表中使用timestamptz,而在CURRENT_TIMESTAMP中使用。参见:

本文链接:https://www.f2er.com/2905654.html

大家都在问