SQLazy:按账户分组,间隔超 1 小时则重置序列号

问题描述:按账户分组,序列号在每次活动间隔超过 1 小时后重置

一张表包含 account_number 和 dt 两个字段。每个账户的记录按时间排序,需要生成一个序列号 Seq。规则如下:

  • 按账户分组,按日期时间升序处理

  • 如果当前行的活动时间与上一行的时间间隔超过 1 小时,则序列号重置为 1

  • 否则(间隔 ≤ 1 小时),序列号递增 1

源数据:

account_number dt

19 2024-04-03 07:02:02

19 2024-04-03 07:02:41

19 2024-04-03 14:58:49

19 2024-04-03 19:58:49

19 2024-04-05 14:58:49

19 2024-04-05 14:59:31

19 2024-04-17 23:56:13

20 2024-04-17 23:59:13

19 2024-04-18 00:15:13

19 2024-04-18 14:56:13

20 2024-04-18 07:41:55

20 2024-04-18 19:41:55

20 2024-04-18 19:56:55

19 2024-04-19 07:41:55

19 2024-04-19 07:42:20

19 2024-04-19 08:41:20

期望结果

19 2024-04-03 07:02:02 1

19 2024-04-03 07:02:41 2

19 2024-04-03 14:58:49 1

19 2024-04-03 19:58:49 1

19 2024-04-05 14:58:49 1

19 2024-04-05 14:59:31 2

19 2024-04-17 23:56:13 1

19 2024-04-18 00:15:13 2

19 2024-04-18 14:56:13 1

19 2024-04-19 07:41:55 1

19 2024-04-19 07:42:20 2

19 2024-04-19 08:41:20 3

20 2024-04-17 23:59:13 1

20 2024-04-18 07:41:55 1

20 2024-04-18 19:41:55 1

20 2024-04-18 19:56:55 2

SQLazy 分步实现

Value

Anchor

Statement

t2

numEvents

sort account_number asc, dt asc

t3


segment condition ((dt[-1] elapse 3600 second)<= dt) partition account_number as grp



compute # as seq partition account_number, grp

下面分别解释这些步骤。

第 1 步:按账户和日期时间升序排序

sort account_number asc, dt asc

将原始数据按 account_number 和 dt 升序排列。这一步确保每个账户内的记录按时间先后顺序处理。

..

第 2 步:分段 - 判断是否超过 1 小时,生成组号

segment condition ((dt[-1] elapse 3600 second)<= dt) partition account_number as grp

在每个账户分区内,依次检查当前行的 dt 与上一行的 dt 是否间隔超过 1 小时(3600 秒)。条件 (dt[-1] elapse 3600 second) <= dt 的含义是:“上一行的时间加上 3600 秒后,是否小于等于当前行的时间”。如果成立,说明间隔 ≥ 1 小时,则新开一个组;否则与上一行同组。最终为每个记录生成一个组号 grp。

..

第 3 步:在每个 (account_number, grp) 内生成组内序号

compute # as seq partition account_number, grp

#表示按分区内的当前顺序自动生成的序号(从 1 开始)。这里按账户和组号分区,在每个分区内按原顺序(已排序)生成序号 seq。这正是我们需要的序列号。

执行后,最终输出如下:

..

最后删除辅助列 grp(或直接输出所需列)即可得到期望结果。

编译生成 SQL

完成上述步骤后,通过 SQLazy 的编译器可以生成等价的原生 SQL,无需手动编写。

..

以下是生成的目标数据库语句(以 MySQL 为例):


你不需要读懂或调试这段 SQL,只需确认前面三步的逻辑正确,编译器就会输出可运行的代码。

列个表格总结一下:

维度

传统 SQL

SQLazy

步骤数

多层 CTE + 窗口函数 + 时间差计算

3 步(排序→分段→生成序号)

核心技巧

用 LAG 计算时间差,累加标记分组

直接用 segment condition 描述间隔规则

可读性

低,需要理解偏移窗口和边界条件

高,条件表达式直接对应业务语言

调试方式

手动拆解 CTE,反复运行验证

单步执行,每一步中间结果可见

跨数据库

需手动调整时间运算语法(例如 SQL Server 用 DATEADD)

编译器自动生成对应方言

这个实例展示了 SQLazy 处理“基于时间间隔的会话划分”类问题的简洁性:通过 segment condition 直接描述“超过 1 小时就新开一组”,再配合分区内行号,完美映射了业务需求。

SQLazy 在线体验sqlazy.com(免费,无需注册)
SQLazy 项目仓库github.com/SPLWare/SQLazy