KDB函数式聚合查询:如何返回分组后的所有价格而非聚合值?
最佳实现方案:灵活分组聚合(兼容全量列保留)
针对你的需求——既要对部分列应用聚合函数(比如time取last、size取min),又要保留price列的所有组内值,最贴合Kdb+原生语法且灵活度最高的方式是直接基于q的原生查询逻辑封装一个通用函数,允许你自由定义每列的处理规则。
1. 核心思路
Kdb+的分组查询?在处理输出列时,支持两种定义方式:
- 聚合模式:
(聚合函数; 列名),比如(last;time)表示对组内time`列取最后一个值 - 全量保留模式:直接写列名,比如
price表示收集组内price列的所有元素为列表
我们可以封装一个函数,直接接收这种规则字典作为参数,完全贴合原生语法,不需要额外的复杂转换。
2. 实现代码
// 通用分组聚合函数:支持混合聚合运算与全量列保留 aggrFlex:{[groupCol; spec; tab] ?[tab;(); groupCol; spec] }
3. 调用示例
按照你的需求,按sym分组,time取最后值、size取最小值、price保留所有值,调用方式如下:
// 先确保表和数据已存在 trade:([]time:`time$();sym:`symbol$();price:`float$();size:`int$()); `trade insert(5?09:30:00.000;5?`a`b;5?10.75;5?100); // 执行分组查询 aggrFlex[`sym; `time`size`price!((last;`time);(min;`size);`price); `trade]
执行后返回的结果中,每个sym对应的price列会是一个包含该组所有价格的列表,而time和size则是聚合后的单一值,完全符合你的预期。
4. 额外兼容方案(可选)
如果你想保留原aggr函数的“函数列表+列列表”调用风格,可以做一个兼容版本,用null标记需要保留全量的列:
// 兼容原调用方式的版本,用null表示保留全量列 aggrCompat:{[fList; colList; groupCol; tab] spec: colList!({$[null x; y; (x;y)]}')'[fList; colList]; ?[tab;(); groupCol; spec] } // 调用示例:price列对应null,即保留全量 aggrCompat[(last;min;::); (`time`size`price); `sym; `trade]
为什么这是最佳方式?
- 原生语法贴合:直接复用Kdb+内置查询的逻辑,学习成本低,不易出错
- 极致灵活性:不仅支持聚合和全量保留,还能直接在规则字典中使用复杂表达式(比如
(sum;size*price)计算成交额) - 可读性强:规则字典清晰展示每列的处理逻辑,维护起来非常直观
内容的提问来源于stack exchange,提问作者user9475848
相关产品推荐
相关产品推荐

