如何从KDB的函数式查询语句中提取日期范围?
解析Kdb+函数式查询的日期范围
需求背景
给定以下Kdb+函数式查询语句(注:原语句存在语法错误,已修正):
// a. 查询最近5天的数据(含当天) ?[tab;enlist (within;`date;(-;`.z.D;5);`.z.D);0b;()] // b. 查询5天前之后的数据(不含5天当天) ?[tab;enlist (>;`date;(-;`.z.D;5));0b;()] // c. 查询指定两天的数据 ?[tab;enlist (in;`date;2023.03.30 2023.03.31);0b;()]
需要实现函数 .util.getDateRange wc,其中wc为上述查询中的where子句,函数需返回对应的日期范围:
- 传入a的where子句,返回
2023.03.26 2023.03.31(假设.z.D为2023.03.31) - 传入c的where子句,返回
2023.03.30 2023.03.31 - 支持复杂场景,如
select from tab where date>2023.03.15对应的where子句,需返回2023.03.16 .z.D
原方案通过虚拟表查询获取范围,但不适用于生产环境,需更优解。
解决方案:直接解析Where子句结构
通过递归解析where子句的嵌套结构,求值动态表达式,提取并合并日期边界,无需创建虚拟表,性能更优。
实现代码
1. 辅助表达式求值函数
用于解析where子句中的动态计算式(如(-;.z.D;5)`):
.util.evalExpr:{[expr] if[not islist expr; :expr]; $[ expr[0] in `within`in`>`>=`<`<=; :expr; 1=count expr; :.util.evalExpr expr[0]; :@[expr[0]; .util.evalExpr each expr[1:]; ()] ] }
2. 主日期范围解析函数
.util.getDateRange:{[wc] // 默认日期范围(可根据业务调整) minDate:1950.01.01; maxDate:.z.D; // 筛选出所有针对`date`列的条件 dateConds:where each {x[1]=`date} each wc; if[0=count dateConds; :minDate maxDate]; // 初始化结果范围 range:(minDate; maxDate); // 遍历处理每个date条件 { cond:.util.evalExpr x; op:cond[0]; val:cond[2]; $[ op=`within; range[0]:max range[0] val[0]; range[1]:min range[1] val[1]; op=`in; range[0]:max range[0] min val; range[1]:min range[1] max val; op=`>; range[0]:max range[0] val+1; op=`>=; range[0]:max range[0] val; op=`<=; range[1]:min range[1] val; op=`>; range[1]:min range[1] val-1; ]; range::range } each dateConds; // 返回日期范围列表 range[0] range[1] }
测试验证
// 测试案例a:最近5天范围 wcA:enlist (within;`date;(-;`.z.D;5);`.z.D); .util.getDateRange wcA // 输出:.z.D-5 .z.D // 测试案例b:5天前之后的范围 wcB:enlist (>;`date;(-;`.z.D;5)); .util.getDateRange wcB // 输出:(.z.D-5)+1 .z.D // 测试案例c:指定日期列表的范围 wcC:enlist (in;`date;2023.03.30 2023.03.31); .util.getDateRange wcC // 输出:2023.03.30 2023.03.31 // 测试多条件场景 wcD:enlist (>;`date;2023.03.15), enlist (<=;`date;2023.04.01); .util.getDateRange wcD // 输出:2023.03.16 2023.04.01
方案优势
- 直接解析结构,无虚拟表开销,适合生产环境
- 支持动态表达式求值(如
.z.D相关计算) - 自动合并多日期条件的交集范围
- 可扩展支持更多操作符(如
between等)
内容的提问来源于stack exchange,提问作者Alex R.
相关产品推荐
相关产品推荐

