sql - 基于非模式特定的列值序列检索未知值
问题描述
我想根据相关的事件值返回和操作时间值,但前提是发生特定的事件序列。下面是一个简化的示例表:
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+-------------+-------+
| id | event1 | time1 | event2 | time2 | event3 | time3 | event4 | time4 | event5 | time5 |
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+-------------+-------+
| abc123 | firstevent | 10:00 | secondevent | 10:01 | thirdevent | 10:02 | fourthevent | 10:03 | fifthevent | 10:04 |
| abc123 | thirdevent | 10:10 | secondevent | 10:11 | thirdevent | 10:12 | firstevent | 10:13 | secondevent | 10:14 |
| def456 | thirdevent | 10:20 | firstevent | 10:21 | secondevent | 10:22 | thirdevent | 10:24 | fifthevent | 10:25 |
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+-------------+-------+
对于此表,我们希望在此特定事件序列发生时检索时间:firstevent
、secondevent
、thirdevent
和任何非零值的最终事件。这意味着返回的相关条目如下:
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+------------+-------+
| id | event1 | time1 | event2 | time2 | event3 | time3 | event4 | time4 | event5 | time5 |
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+------------+-------+
| abc123 | firstevent | 10:00 | secondevent | 10:01 | thirdevent | 10:02 | fourthevent | 10:03 | null | null |
| null | null | null | null | null | null | null | null | null | null | null |
| def456 | null | null | firstevent | 10:21 | secondevent | 10:22 | thirdevent | 10:24 | fifthevent | 10:26 |
+--------+------------+-------+-------------+-------+-------------+-------+-------------+-------+------------+-------+
如上所示,列与序列的出现无关,从event1
和event2
列开始返回两个结果,因此解决方案应该是独立的并支持 n 列。然后可以通过在 3 个固定变量之后的序列中发生的最终非零事件聚合这些值,以给出如下所示的内容:
+-------------+-------------------------------+
| FinalEvent | AverageTimeBetweenFinalEvents |
+-------------+-------------------------------+
| fourthevent | 1:00 |
| fifthevent | 2:00 |
+-------------+-------------------------------+
解决方案
以下是 BigQuery 标准 SQL
#standardSQL
WITH search_events AS (
SELECT ['firstevent', 'secondevent', 'thirdevent'] search
), temp AS (
SELECT *, REGEXP_EXTRACT(events, CONCAT(search, r',(\w*)')) FinalEvent
FROM (
SELECT id, [time1, time2, time3, time4, time5] times,
(SELECT STRING_AGG(event) FROM UNNEST([event1, event2, event3, event4, event5]) event) events,
(SELECT STRING_AGG(search) FROM UNNEST(search) search) search
FROM `project.dataset.table`, search_events
)
)
SELECT FinalEvent,
times[SAFE_OFFSET(ARRAY_LENGTH(REGEXP_EXTRACT_ALL(REGEXP_EXTRACT(events, CONCAT(r'(.*?)', search, ',', FinalEvent )), ',')) + 3)] time
FROM temp
WHERE IFNULL(FinalEvent, '') != ''
如果适用于您的问题的样本数据 - 结果是
Row FinalEvent time
1 fourthevent 10:03
2 fifthevent 10:25
所以,正如您所看到的 - 所有最终事件都与它们各自的时间一起被提取
现在,您可以在这里进行任何您需要的分析 - 我不确定背后的逻辑AverageTimeBetweenFinalEvents
,所以我把这个留给你 - 特别是我认为主要问题的重点是提取那些最终事件
你能提供这个陈述背后的逻辑吗?
times[SAFE_OFFSET(ARRAY_LENGTH(REGEXP_EXTRACT_ALL(REGEXP_EXTRACT(events, CONCAT(r'(.*?)', search, ',', FinalEvent )), ',')) + 3)] time
当然,希望下面有助于了解该表达式背后的逻辑
- 组装正则表达式以提取匹配事件之前发生的事件列表
- 提取那些事件
- 将所有逗号提取到数组中
- 通过取上述数组中的逗号数 + 3 来计算最终事件的位置(三是反映搜索序列中的位置数)
- 提取相应的时间作为时间数组的元素
推荐阅读
- python - 谷歌 api 令牌已过期或被撤销?
- c - gethostbyname() 函数的源码实现在哪里?
- c# - 为什么用户控件的 WPF 上下文菜单只显示用户控件中的特定位置?
- javascript - 使用 mongoose 获取路由的错误处理
- python - 使用火箭的 Python 列表理解
- django - 基于 Django 类的视图加载另一个带有数据的表单
- python - 命名python变量
- javascript - 从另一个 React 文件调用函数
- javascript - MongoError:不能两次调用 abortTransaction;MongoError:调用 commitTransaction 后无法调用 abortTransaction
- python - 无法注册 pytest 辅助函数