是否有可能在 SQL 中获得每小时的活动会话数?

Is it possible to get active sessions per hour in SQL?

start_time end_time 主机ID 游戏ID
2021/6/1420:13 2021/6/1422:22 1 AB1
2021/6/1420:20 2021 年 6 月 14 日 21:47 2 AB2
2021/6/1420:22 2021/6/1422:07 3 AB3
2021 年 6 月 14 日 20:59 2021/6/1421:15 4 AB4
2021 年 6 月 15 日 21:24 2021 年 6 月 15 日 22:09 1 AB5
2021 年 6 月 15 日 21:24 2021/6/1521:59 2 AB6
2021 年 6 月 15 日 23:11 2021 年 6 月 16 日 01:22 4 AB7
2021 年 6 月 16 日 20:13 2021 年 6 月 16 日 21:23 3 AB8

我有一个 table 有开始时间和结束时间。我想计算每小时活跃的游戏室。我知道我至少应该尝试解决这个问题,但我真的不知道从哪里开始,或者这是否可能 SQL.

我首先做的是使用 start_time 计算一个小时内有多少个 gameID。但我确定我没有回答 'active' per session 问题。我所做的只是计算每小时有多少人开始玩游戏。

预期的结果是这样的

工作日

时间 有效
6/14/2021 2000 4
6/15/2021 2100 4
6/16/2021 2200 2
6/15/2021 2100 2
6/16/2021 2200 1
6/17/2021 2300 1
2021 年 6 月 16 日 0 1
2021 年 6 月 17 日 1 1
6/18/2021 2000 1
6/19/2021 2100 1

或者不按天分组的每小时活动会话数。

小时

时间 有效
2000 5
2100 7
2200 3
2300 1
0000 1
0001 1

一个简单的方法是对数据进行逆透视然后聚合。获取数据中任意时刻的数字:

with se as (
      select start_time as time, 1 as inc from t
      union all
      select end_time, -1 as inc from t
     )
select time, sum(sum(inc)) over (order by time) as actives
from se
group by time;

然后,您需要定义“每小时”的含义。您可以使用 trunc():

获得每小时的第一个结果
with se as (
      select start_time as time, 1 as inc from t
      union all
      select end_time, -1 as inc from t
     )
select time, sum(sum(inc)) over (order by time) as actives
from se
group by time
qualify row_number() over (partition by date_trunc(time, hour) order by time) = 1;

我建议以下解决方案

select timestamp_trunc(minute, hour) hour, 
  count(distinct hostid) hosts,
  count(distinct gameid) games
from `project.dataset.table`, 
unnest(generate_timestamp_array(
  parse_timestamp('%m/%d/%Y %H:%M', start_time), 
  parse_timestamp('%m/%d/%Y %H:%M', end_time), 
  interval 1 minute)) minute
group by hour
# order by hour          

如果应用于您问题中的示例数据(最后一行修复了 end_time - 应该是 6/16/2021 21:23 - 而不是 6/6/2021 21:23 ) - 输出是

简要说明

  1. Expand/split 每个原始行在 start_timeend_time
  2. 之间每分钟变成一行
  3. 然后,简单地通过 hour 应用 count(distinct ...)
  4. 进行聚合

Or count of active sessions per hour without grouping by day.

您可以应用完全相同的方法

select extract(hour from minute) hour, 
  count(distinct hostid) hosts,
  count(distinct gameid) games
from `project.dataset.table`, 
unnest(generate_timestamp_array(
  parse_timestamp('%m/%d/%Y %H:%M', start_time), 
  parse_timestamp('%m/%d/%Y %H:%M', end_time), 
  interval 1 minute)) minute
group by hour
order by hour             

有输出