计算最大并发用户会话数[英] Calculate maximum number of concurrent user sessions

本文是小编为大家收集整理的关于计算最大并发用户会话数的处理方法,想解了计算最大并发用户会话数的问题怎么解决?计算最大并发用户会话数问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我在 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并发用户会话数,但在同一时间点存在并发意味着,在我的情况下,我需要检查它们是否重叠至少 30 分钟

推荐答案

从每个时间范围的结束(或开始)减去 30 分钟.然后基本上按照我的引用的"简单"答案中所述进行(在任何地方都在正确的方向上调整 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<>小提琴这里

请注意,LOCALTIMESTAMP 取决于当前会话的时区.考虑在您的表中使用 timestamptz 和 CURRENT_TIMESTAMP 代替.见:

本文地址:https://www.itbaoku.cn/post/1764096.html