MJ.*_*MJ. 12 sql postgresql window-functions
我正在尝试为用户关联两种类型的事件.我希望在"A"事件之前看到所有事件"B"以及该用户的最新事件"A".如何实现这一目标?特别是,我正试图在Postgres中做到这一点.
我希望在窗口函数中可以使用"where"子句,在这种情况下,我基本上可以使用"where event ='A'"来执行LAG(),但这似乎不可能.
有什么建议?
数据示例:
|user |time|event|
|-----|----|-----|
|Alice|1 |A |
|Bob |2 |A |
|Alice|3 |A |
|Alice|4 |B |
|Bob |5 |B |
|Alice|6 |B |
Run Code Online (Sandbox Code Playgroud)
期望的结果:
|user |event_b_time|last_event_a_time|
|-----|------------|-----------------|
|Alice|4 |3 |
|Bob |5 |2 |
|Alice|6 |3 |
Run Code Online (Sandbox Code Playgroud)
Che*_*ian 17
刚试过使用PostgreSQL 9.5.4的Gordon的方法,它抱怨说
对于非聚合窗口函数,未实现FILTER
这意味着使用lag()与FILTER是不允许的.所以我使用max()不同的窗口框架和CTE 修改了Gordon的查询:
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';
Run Code Online (Sandbox Code Playgroud)
验证这适用于PostgreSQL 9.5.4.
感谢戈登的FILTER伎俩!
这是一种方法:
select t.*
from (select t.*,
lag(time) filter (where event = 'A') (partition by user order by time)
from t
) t
where event = 'B';
Run Code Online (Sandbox Code Playgroud)
相关子查询/横向联接可能会具有更好的性能。
这里不需要窗口函数。只需查找所有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';
Run Code Online (Sandbox Code Playgroud)
我假设该表已被调用t(我使用了两次)。
| 归档时间: |
|
| 查看次数: |
11941 次 |
| 最近记录: |