SQL - 基于时间线的查询
Posted
技术标签:
【中文标题】SQL - 基于时间线的查询【英文标题】:SQL - timeline based queries 【发布时间】:2020-12-13 11:04:59 【问题描述】:我有一个事件表,其中有:
user_id 事件名称 event_time类型有事件名称:meeting_started
、meeting_ended
、email_sent
我想创建一个查询来计算会议期间电子邮件的发送次数。
更新:我正在使用 Google BigQuery。
查询示例:
SELECT
event_name,
count(distinct user_id) users,
FROM
events_table WHERE
and event_name IN ('meeting_started', 'meeting_ended')
group by 1
我怎样才能做到这一点? 谢谢!
【问题讨论】:
会议可以重叠吗?如果数据中存在异常情况,例如似乎永远不会结束的会议怎么办? 【参考方案1】:您可以在 BigQuery 中使用 last_value()
执行此操作:
如果最近的“会议”事件是'meeting_started'
,则可能会在会议期间发送一封电子邮件。因此,您可以通过获取每个事件的最新会议事件然后过滤来解决此问题:
select et.*
from (select et.*,
last_value(case when event_name in ('meeting_started', 'meeting_ended') then event_name end) ignore nulls) over
(partition by user_id order by event_time) as last_meeting_event
from events_table et
) et
where event_name = 'email_sent' and last_meeting_event = 'meeting_started'
【讨论】:
【参考方案2】:这看起来像是某种间隙和岛屿问题,其中一个岛屿是一个会议,而您想要属于岛屿的电子邮件。
我们如何定义一个岛屿?假设会议开始和结束正确交错,我们可以按每个用户比较开始和结束的计数。如果开始的次数多于结束的次数,则会议正在进行中。使用此逻辑,您可以获取在会议期间发送的所有电子邮件,如下所示:
select *
from (
select e.*,
countif(event_name = 'meeting_started') over(partition by user_id order by event_time) as cnt_started,
countif(event_name = 'meeting_ended' ) over(partition by user_id order by event_time) as cnt_ended
from events_table e
) e
where event_name = 'email_sent' and cnt_started > cnt_ended
目前还不清楚你想从这里去哪里。如果您想计算此类电子邮件的数量,只需在外部查询中使用select count(*)
而不是select *
。
【讨论】:
以上是关于SQL - 基于时间线的查询的主要内容,如果未能解决你的问题,请参考以下文章