【发布时间】:2018-10-30 11:19:14
【问题描述】:
我有一个问题应该在 SQL 之外解决,但由于业务限制需要在 SQL 内部解决。
- 所以,请不要告诉我在 SQL 之外的数据摄取时执行此操作,我想这样做,但这不是一个选项...
我有一个事件流,有 4 个主要属性....
- 源设备
- 事件的时间戳
- 事件的“类型”
- 事件的“有效负载”(代表各种数据类型的可怕 VARCHAR)
我需要做的是将流分成几部分(我将其称为“会话”)。
- 每个会话都特定于设备(实际上,
PARTITION BY device_id) - 一个会话不能包含多个相同类型的事件
为了缩短示例,我将它们限制为仅包含时间戳和 event_type...
timestamp | event_type desired_session_id
-----------+------------ --------------------
0 | 1 0
1 | 4 0
2 | 2 0
3 | 3 0
4 | 2 1
5 | 1 1
6 | 3 1
7 | 4 1
8 | 4 2
9 | 4 3
10 | 1 3
11 | 1 4
12 | 2 4
理想化的最终输出可能是对最终结果的透视...
device_id | session_id | event_type_1_timestamp | event_type_1_payload | event_type_2_timestamp | event_type_2_payload ...
(但这还不是一成不变的,但我需要“知道”哪些事件构成一个会话,它们的时间戳是什么,以及它们的有效负载是什么。可能只是附加 session_id只要我不“丢失”其他属性,输入的列就足够了。)
有:
- 12 种离散事件类型
- 数十万台设备
- 每台设备有数十万个事件
- 每个“会话”大约 6-8 个事件的“标准”
- 但有时一个会话可能只有 1 个或全部 12 个
这些因素意味着半笛卡尔积之类的,嗯,不太理想,但可能是“唯一的方法”。
我(在我的脑海中)玩过分析函数和间隙和孤岛类型的过程,但永远无法做到。我总是回退到一个我“想要”一些标志的地方,我可以将它们从一行带到另一行并根据需要重置它们......
在 SQL 中不起作用的伪代码...
flags = [0,0,0,0,0,0,0,0,0]
session_id = 0
for each row in stream
if flags[row.event_id] == 0 then
flags[row.event_id] = 1
else
session_id++
flags = [0,0,0,0,0,0,0,0,0]
row.session_id = session_id
对此的任何 SQL 解决方案都表示赞赏,但如果您还可以考虑“同时发生”的事件,您将获得“奖励积分”...
If multiple events happen at the same timestamp
If ANY of those events are in the "current" session
ALL of those events go in to a new session
Else
ALL of those events go in to the "current" session
If such a group of event include the same event type multiple times
Do whatever you like
I'll have had enough by that point...
But set the session as "ambiguous" or "corrupt" with some kind of flag?
【问题讨论】:
-
。 .我更喜欢有答案的棘手问题;)这是一个有趣的问题。
-
@GordonLinoff - 添加了我基于
LAG()的“蛮力”方法。可怕,但不如 RBAR 循环那么糟糕。
标签: sql session amazon-redshift event-stream