KDB Q+查询需求:基于ID/NAME对比前后日字段变化返回差异行
KDB Q+ 查询实现:对比当日与最近前一日数据变化
现有KDB表
| Date | ID | NAME | BALANCE |
|---|---|---|---|
| 2024-01-01 | 1 | ABC | 23000 |
| 2024-01-01 | 2 | XYZ | 14000 |
| 2024-01-02 | 1 | ABC | 23500 |
| 2024-01-02 | 2 | XYZ | 14000 |
| 2024-01-03 | 1 | ABC | 1400 |
| 2024-01-03 | 2 | XYZ | 23000 |
| 2024-01-04 | 1 | ABC | 1400 |
| 2024-01-04 | 2 | XYZ | 23000 |
| 2024-01-07 | 1 | ABC | 1000 |
| 2024-01-07 | 2 | XYZ | 3000 |
查询需求
基于ID和NAME,将当日数据与最近的前一日(间隔1-3天)的数据对比,仅返回BALANCE或字符串字段(如NAME)发生变化的行。
预期结果
- 执行日期为2024-01-02时,返回:
| Date | ID | NAME | BALANCE |
|---|---|---|---|
| 2024-01-02 | 1 | ABC | 23500 |
- 执行日期为2024-01-07时,返回:
| Date | ID | NAME | BALANCE |
|---|---|---|---|
| 2024-01-07 | 1 | ABC | 1000 |
| 2024-01-07 | 2 | XYZ | 3000 |
实现方案
步骤1:定义目标日期
先指定要查询的当日日期,可使用系统日期或手动指定:
targetDate: .z.d; // 自动取当前系统日期 // 或手动指定如 targetDate: 2024.01.02
步骤2:关联当日与最近前一日数据
按ID和NAME分组,提取每个分组中早于目标日期的最近一条记录,再与当日数据左连接:
// 筛选当日数据 todayData: select from table where Date = targetDate; // 筛选历史数据并取每个分组的最近记录 prevData: select last Date as prevDate, last BALANCE as prevBALANCE, last NAME as prevNAME by ID, NAME from table where Date < targetDate; // 左连接关联两组数据 joined: lj[todayData; prevData];
步骤3:筛选变化行
对比BALANCE和NAME字段,保留有变化的记录:
// 筛选条件:BALANCE与前一日不等,或NAME发生变化 result: select Date, ID, NAME, BALANCE from joined where BALANCE <> prevBALANCE or NAME <> prevNAME;
完整可测试脚本
// 初始化测试表(新手可直接运行) table: ([] Date: 2024.01.01 2024.01.01 2024.01.02 2024.01.02 2024.01.03 2024.01.03 2024.01.04 2024.01.04 2024.01.07 2024.01.07; ID: 1 2 1 2 1 2 1 2 1 2; NAME: `ABC`XYZ`ABC`XYZ`ABC`XYZ`ABC`XYZ`ABC`XYZ; BALANCE: 23000 14000 23500 14000 1400 23000 1400 23000 1000 3000); // 指定目标日期,替换为2024.01.02可测试第一个场景 targetDate: 2024.01.07; // 执行查询逻辑 todayData: select from table where Date = targetDate; prevData: select last Date as prevDate, last BALANCE as prevBALANCE, last NAME as prevNAME by ID, NAME from table where Date < targetDate; joined: lj[todayData; prevData]; result: select Date, ID, NAME, BALANCE from joined where BALANCE <> prevBALANCE or NAME <> prevNAME; // 输出结果 result
关键说明
last by ID, NAME自动处理日期间隔问题,确保取到每个分组的最近历史记录lj(左连接)保证当日所有记录都能关联到对应分组的历史数据- 筛选条件可根据实际字符串字段扩展,比如新增其他需要对比的字段
内容的提问来源于stack exchange,提问作者D3110
相关产品推荐
相关产品推荐

