我试图为用户关联两种类型的事件。我希望看到所有活动" B"以及最近的活动" A"对于该用户之前的" A"事件。如何实现这一目标?特别是,我试图在Postgres中这样做。
我希望有可能使用"其中"窗口函数中的子句,在这种情况下我基本上可以使用"其中event =' A'""""""""'
有什么建议吗?
数据示例:
|user |time|event|
|-----|----|-----|
|Alice|1 |A |
|Bob |2 |A |
|Alice|3 |A |
|Alice|4 |B |
|Bob |5 |B |
|Alice|6 |B |
期望的结果:
|user |event_b_time|last_event_a_time|
|-----|------------|-----------------|
|Alice|4 |3 |
|Bob |5 |2 |
|Alice|6 |3 |
答案 0 :(得分:15)
使用PostgreSQL 9.5.4尝试了Gordon的方法,它抱怨
未对非聚合窗口函数实施FILTER
这意味着不允许将lag()
与FILTER
一起使用。所以我使用max()
,一个不同的窗口框架和CTE修改了戈登的查询:
WITH subq AS (
SELECT
"user", event, time as event_b_time,
max(time) FILTER (WHERE event = 'A') OVER (
PARTITION BY "user"
ORDER BY time
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
) AS last_event_a_time
FROM events
ORDER BY time
)
SELECT
"user", event_b_time, last_event_a_time
FROM subq
WHERE event = 'B';
已验证这适用于PostgreSQL 9.5.4。
感谢Gordon的FILTER
技巧!
答案 1 :(得分:4)
这是一种方法:
select t.*
from (select t.*,
lag(time) filter (where event = 'A') (partition by user order by time)
from t
) t
where event = 'B';
相关子查询/横向连接可能具有更好的性能。
答案 2 :(得分:1)
此处不需要窗口功能。只需找到所有B
个事件,并为每个事件通过子查询找到同一用户的最新A
。这样的事情应该这样做:
SELECT
"user",
time AS event_b_time,
(SELECT time AS last_event_a_time
FROM t t1
WHERE "user"=t.user AND event='A' AND time<t.time
ORDER BY time DESC LIMIT 1)
FROM t
WHERE event='B';
我假设该表名为t
(我使用了两次)。