我有一个名为activity
的表,其中包含如下所示的值:
userId | timestamp | action
----------------------------------------
1 | 2022-10-18 10:00:00 | OPEN
2 | 2022-10-18 10:20:00 | OPEN
1 | 2022-10-18 10:05:00 | CLOSE
2 | 2022-10-18 10:22:00 | CLOSE
...
我希望能够得到每个用户在给定的一天中打开和关闭时间的差异,如下所示:
desiredTable
------------------------------------------------------
userId | start_time | time_elapsed_in_minutes
------------------------------------------------------
1 | 2022-10-18 10:00:00 | 5
2 | 2022-10-18 10:20:00 | 2
需要注意的几点是:
1.不能保证OPEN
和CLOSE
行彼此背对背,因为该表还包含许多其他操作类型。
1.此外,由于网络条件的原因,无法保证OPEN
和CLOSE
的行数相同,这可能会导致不报告其中一个。例如:用户1可以具有3个打开和1个关闭,因此仅需要计算1对。
我的方法:
- 为每个用户创建OPEN和CLOSE计数表
userId | # opens | # closes
- 确定哪个数字更小(打开数或关闭数),并从活动表中获取行数
- 打开具有上面确定的行数的表
userId | timestamp
- 使用上面确定的行数关闭表
userId | timestamp
- 从按用户ID分组打开时间戳中减去关闭时间戳,并截短为分钟
如有任何帮助,我们将不胜感激!
3条答案
按热度按时间mum43rcc1#
正如@Robert汉密尔顿所建议的,这可以直接转换为使用window functions的查询:
Fiddle.
但是,使用非常基本的结构也可以实现同样的效果--我在下面使用CTE只是为了可读性:
Fiddle.
我通常认为序列中所有后面的
OPEN
都是第一个的重传,类似于您对CLOSE
的假设,这就是为什么我还添加了longest_open_window_before_a_close
--将最早记录的OPEN
与CLOSE
配对。我发现的一个未提及的细节是
每个用户在指定日期的开始和结束时间之间的差异
我认为这意味着所有打开的窗口都应该在午夜被切断,而所有在接下来的日期被孤立的
CLOSES
都应该被假设为在午夜打开。nzkunb0c2#
我们将每个
action = 'close'
与它前面的action = 'open'
分组,然后按id分组并选择时间戳。| 用户标识|开始时间|已用时间(分钟)|
| - -|- -|- -|
| 一个|2022年10月18日10时00分|00时05分|
| 2个|2022年10月18日10时20分|00时02分|
Fiddle
pbwdgjma3#
当下一个
action
是closed
时,我们可以使用lead()
。| 用户标识|开始时间|已用时间(分钟)|
| - -|- -|- -|
| 一个|2022年10月18日10时00分|00时05分|
| 2个|2022年10月18日10时20分|00时02分|
Fiddle