我有一个问题应该在 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?