计算SQL中特定事件之前和之后的事件数?
Posted
技术标签:
【中文标题】计算SQL中特定事件之前和之后的事件数?【英文标题】:Count number of events before and after a particular event in SQL? 【发布时间】:2018-02-13 15:53:43 【问题描述】:我有一个包含日期和事件的表格。有一个名为“A”的事件。我想知道在 Sql Bigquery 中事件“A”之前和之后发生了多少事件。 例如,
User Date Events
123 2018-02-13 D
123 2018-02-12 B
123 2018-02-10 C
123 2018-02-11 A
123 2018-02-01 X
答案是这样的。
User Event Before After
123 A 2 2
我已经尝试了很多查询,但都不起作用。任何想法,如何解决这个问题?
【问题讨论】:
当然 :o) - 这个例子是不是过于简单了,或者你真的只有一个事件 A 在那个表中?我认为在您最初的问题中,我看到两行带有 A 实际上,它来自我有多个用户的表。每个用户只有一次事件 A,但其他事件重复多次。我为单个用户分离了数据。这样我想如果问题解决了,我可以为整个表实现它。实际的答案是:userid event(i.e A) before value after value. 【参考方案1】:以下是 BigQuery 标准 SQL
#standardSQL
WITH `project.dataset.events` AS (
SELECT 123 user, '2018-02-13' dt, 'D' event UNION ALL
SELECT 123, '2018-02-12', 'B' UNION ALL
SELECT 123, '2018-02-11', 'A' UNION ALL
SELECT 123, '2018-02-10', 'C' UNION ALL
SELECT 123, '2018-02-01', 'X'
)
SELECT user, event, before, after
FROM (
SELECT user, event,
COUNT(1) OVER(PARTITION BY user ORDER BY dt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) before,
COUNT(1) OVER(PARTITION BY user ORDER BY dt ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ) after
FROM `project.dataset.events`
)
WHERE event = 'A'
【讨论】:
在这个答案中,我必须手动合并所有可能的事件。这对于大表来说很难实现。 什么意思?这是你的问题吗? :o) 只需删除WHERE event = 'A'
,您就可以在所有用户的每个事件之前和之后获得!试着让我知道
嘿米哈伊尔,如果我必须更改查询以检查特定事件在 A 之前发生了多少次。但问题是我必须检查的事件包含特定前缀。意味着我必须检查以( X.Y.then 一些事件名称)开头的事件。所以,X.Y.SomeEvent 是我必须设置计数器的事件。有什么想法吗?
我认为,您应该将此作为一个新问题发布,这样我们就不受 cmets 格式的限制【参考方案2】:
对于每个“A”,您可以使用row_number()
和lead()
获取到下一个“A”的事件数:
select t.*,
(lead(seqnum) over (order by date) - seqnum - 1) as num_other_events
from (select t.*, row_number() over (order by date) as seqnum
from t
) t
where event = 'A';
这会为每个“A”生成结果。鉴于您的示例数据中有三个“A”并且只想要“2”,我不确定用于此的逻辑是什么。
【讨论】:
【参考方案3】:如果您想在事件 A 的行之前计算出现在表中的事件数,则无法执行此操作,因为 BigQuery 不会保留表中行的物理顺序。
如果你想使用日期列计算之前和之后,你可以这样做
WITH
events AS (
SELECT
DATE('2018-02-13') AS event_date,
"D" AS event
UNION ALL
SELECT
DATE('2018-02-12') AS event_date,
"B" AS event
UNION ALL
SELECT
DATE('2018-02-10') AS event_date,
"C" AS event
UNION ALL
SELECT
DATE('2018-02-11') AS event_date,
"A" AS event
UNION ALL
SELECT
DATE('2018-02-01') AS event_date,
"X" AS event),
event_a AS (
SELECT
*
FROM
events
WHERE
event = "A")
SELECT
ANY_VALUE(event_a.event) AS Event,
COUNTIF(events.event_date<event_a.event_date) AS Before,
COUNTIF(events.event_date>event_a.event_date) AS After
FROM
events,
event_a
【讨论】:
【参考方案4】:希望这能回答你的问题
Create table #temp(T_date varchar(100),Events varchar(100))
insert into #temp values
('2018-02-13','A'),
('2018-02-12','B'),
('2018-02-10','C'),
('2018-02-11','A'),
('2018-02-01','X'),
('2018-02-06','A')
select max(rn)-min(rn)
from
(
select *,ROW_NUMBER() over(order by (select 1)) as rn from #temp
)a
where Events='A'
【讨论】:
以上是关于计算SQL中特定事件之前和之后的事件数?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Bigquery 中的另一个事件之前计算特定事件的数量?
如何编写 pyspark map-reduce 来计算日期之前的事件数