我有一张这样的table:
Name activity time
user1 A1 12:00
user1 E3 12:01
user1 A2 12:02
user2 A1 10:05
user2 A2 10:06
user2 A3 10:07
user2 M6 10:07
user2 B1 10:08
user3 A1 14:15
user3 B2 14:20
user3 D1 14:25
user3 D2 14:30
字符串
现在,我需要一个这样的结果:
Name activity next_activity
user1 A2 NULL
user2 A3 B1
user3 A1 B2
型
我想为每个用户检查A组的最后一个活动以及B组接下来发生的活动类型(B组的活动总是在A组的活动之后发生)。其他类型的活动对我来说不感兴趣。我尝试使用lead()
函数,但它不起作用。
我如何解决我的问题?
2条答案
按热度按时间ercv8c1e1#
您的定义:
B组的活动总是在A组的活动之后进行。
..逻辑上意味着在1个或多个A活动之后,每个用户有0个或1个B活动。序列中的活动不得超过B。
你可以使用一个窗口函数
DISTINCT ON
和CASE
,这应该是每个用户 * 几 * 行的最快方法(也见下文):字符串
如果没有添加
ELSE
分支,则SQLCASE
表达式默认为NULL
,因此我保持简短。假设
time
定义为NOT NULL
。否则,您可能需要添加NULLS LAST
。为什么?为什么?(activity LIKE 'A%' OR activity LIKE 'B%')
比activity ~ '^[AB]'
更详细,但在旧版本的Postgres中通常更快。关于模式匹配:条件窗口函数?
这实际上是可能的。您可以将聚合
FILTER
子句与窗口函数的OVER
子句结合使用。然而:FILTER
子句本身只能处理当前行中的值。1.更重要的是,
FILTER
并不是为像lead()
或lag()
(最高Postgres 13)这样的纯正版函数实现的-只为aggregate functions实现。如果您尝试:
型
Postgres会告诉你:
型
关于
FILTER
:性能
对于***few***用户,每个用户有***few***行,即使没有索引,几乎任何查询都是快速的。
对于***多***个用户和每个用户***少***行,上面的第一个查询应该是最快的。请参阅:
对于每个用户 * 许多 * 行,有(可能 * 很多 *)更快的技术,这取决于您的设置细节。请参阅:
s71maibg2#
字符串