SQL - 获取只有进入和退出日期的 MAX COUNT 访问峰值

SQL - Get the MAX COUNT access peak having only entrance and exit date

我有一个 table 可以保持对我们系统的访问,它有两列,分别称为 entryTime 和 exitTime

例如:

entranceTime            exitTime
2021-09-09 20:03:31+00  2021-09-09 20:05:39+00
2021-09-09 20:03:58+00  2021-09-09 20:05:11+00
2021-09-09 20:04:29+00  2021-09-09 20:05:36+00
2021-09-09 20:04:09+00  2021-09-09 20:04:28+00
2021-09-09 20:05:15+00  2021-09-09 20:05:30+00

我试图获得的是同时连接的“峰值”,我尝试使用子查询 像这样使用 MAX 和 COUNT:

SELECT Max((SELECT Count("a"."id")
            FROM   "public"."access" "a"
            WHERE  "a"."entrancetime" >= "a2"."entrancetime"
                   AND a."entrancetime" <= "a2"."exittime"))
FROM   "public"."access" a2

但是通过这个查询我得到的计数是 5 而不是 3,是否可以仅使用这两列并仅使用 SQL 来实现这一点?谢谢你的时间。

“高峰”将出现在其中一个入场时间。您可以使用相关子查询来计算每一行的并发行数。然后得到峰值:

select max(num_concurrent)
from (select a.*,
             (select count(*)
              from "public"."access" a2
              where a2.exittime >= a.entrancetime and
                    a2.entrancetime <= a.entrancetime
             ) as num_concurrent
      from "public"."access" a
     ) a;

上面的方法可能不太好扩展,所以其实还有更高效的方法。您可以逆轴旋转时间并使用累计和:

select v.t, sum(v.inc) as net_inc,
       sum(sum(v.inc)) over (order by v.t) as num_concurrent
from "public"."access" a cross join lateral
     (values (a.entrancetime, 1), (a.exittime, -1)
     ) v(t, inc)
group by v.t
order by num_concurrent desc
limit 1;

Here 是一个 db<>fiddle.

您的比较有点偏差,请参阅下面的修改示例 fiddle

SELECT MAX((SELECT Count("a"."entranceTime")
            FROM   "public"."access_times" "a"
            WHERE  "a2"."entranceTime" >= "a"."entranceTime"
                   AND "a2"."entranceTime" <= "a"."exitTime"))
            
FROM   "public"."access_times" a2

View live demo

同样下面的例子使用内连接来确定入口时间的重叠时间,最后使用max来确定这个子查询的峰值时间。

识别重叠时间的子查询

SELECT 
        "a"."entranceTime",Count(1) as cnt
    FROM   
        "public"."access_times" "a"
    INNER JOIN
        "public"."access_times" "a2"
            ON  "a"."entranceTime" >= "a2"."entranceTime"
             AND a."entranceTime" <= "a2"."exitTime"
    GROUP BY "a"."entranceTime";
entranceTime cnt
2021-09-09T20:03:58.000Z 2
2021-09-09T20:03:31.000Z 1
2021-09-09T20:05:15.000Z 3
2021-09-09T20:04:29.000Z 3
2021-09-09T20:04:09.000Z 3

一种检索重叠数的方法

SELECT 
    MAX(cnt) as peak 
FROM (
    SELECT 
        Count(1) as cnt
    FROM   
        "public"."access_times" "a"
    INNER JOIN
        "public"."access_times" "a2"
            ON  "a"."entranceTime" >= "a2"."entranceTime"
             AND a."entranceTime" <= "a2"."exitTime"
    GROUP BY "a"."entranceTime"
) t;
peak
3

使用重叠次数检索峰值时间

SELECT 
        "a"."entranceTime" as peak_time,Count(1) as no_occurrences
    FROM   
        "public"."access_times" "a"
    INNER JOIN
        "public"."access_times" "a2"
            ON  "a"."entranceTime" >= "a2"."entranceTime"
             AND a."entranceTime" <= "a2"."exitTime"
    GROUP BY "a"."entranceTime"
    ORDER BY Count(1) DESC
    LIMIT 1;
peak_time no_occurrences
2021-09-09T20:05:15.000Z 3

SELECT 
        Count(1) as no_occurrences
    FROM   
        "public"."access_times" "a"
    INNER JOIN
        "public"."access_times" "a2"
            ON  "a"."entranceTime" >= "a2"."entranceTime"
             AND a."entranceTime" <= "a2"."exitTime"
    GROUP BY "a"."entranceTime"
    ORDER BY Count(1) DESC
    LIMIT 1;
no_occurrences
3

View on DB Fiddle

让我知道这是否适合你