在 kdb 中,在不等式的多列上是否存在等效的左连接(如 asof 连接的可修改版本)?
In kdb, is there an equivalent of left join on multiple columns with inequalities (like a modifiable version of asof joins)?
我在kdb有一个订单table,里面有订单id,订单输入时间和订单删除时间,如下图:
+----+-------------------------+-------------------------+
| id | entrytime | deletetime |
+----+-------------------------+-------------------------+
| 1 | 2020.01.01T00:00:00.000 | 2020.01.01T04:00:00.000 |
| 2 | 2020.01.01T00:00:00.000 | 2020.01.01T03:59:58.000 |
| 3 | 2020.01.01T00:00:00.000 | 2020.01.01T00:00:02.000 |
|... | ... | ... |
+----+-------------------------+-------------------------+
我想将其转换为每秒显示 open/active 个订单的视图,如下所示:
+-------------------------+---------+
| datetime | openids |
+-------------------------+---------+
| 2020.01.01T00:00:00.000 | 1 2 3 |
| 2020.01.01T00:00:01.000 | 1 2 3 |
| 2020.01.01T00:00:02.000 | 1 2 |
| 2020.01.01T00:00:03.000 | 1 2 |
| ... | ... |
| 2020.01.01T03:59:57.000 | 1 2 |
| 2020.01.01T03:59:58.000 | 1 |
| 2020.01.01T03:59:59.000 | 1 |
| 2020.01.01T04:00:00.000 | |
+-------------------------+---------+
我需要的是相当于
SELECT * FROM table1 LEFT JOIN ON datetime >= entrytime and datetime < deletetime
在 kdb 中。
我已经尝试 window 加入但收效甚微。
非常感谢任何帮助。
有很多选择可以做到这一点。请看下面的其中一个。
但首先我会将时间转换为 timestamp
类型,datetime
很难处理并且被认为已过时。
t: ([] id: 1 2 3
; entrytime: 3#2020.01.01D
; deletetime: 2020.01.01D04:00:00 2020.01.01D03:59:58 2020.01.01D00:00:02);
t: update datetime: {x+00:00:01*til `inte-9*y-x}'[entrytime;deletetime] from t;
t: ungroup t;
t: select openid: id by datetime from t;
timetable: ([]datetime: {x+00:00:01*til 2+`inte-9*y-x} . value exec min datetime
, max datetime from t);
t: timetable lj t;
t
解释:
- 将日期时间列添加到 table
t
以一秒钟的步骤跟踪所有可用订单的时间
ungroup
table t
获取id<->可用时间映射
- 按可用时间分组 table
t
。这已经给出了您正在寻找的结果。但是在没有可用订单的时候可能会有空档
- 通过加入
timetable
填补空白,其中所有时间都在订单的 create/delete 时间范围内,table t
.
可以在不使用任何类型的连接的情况下在一行中完成此操作:
q)`datetime xgroup ungroup select id,datetime:entrytime+"v"$til each"j"$deletetime.second-entrytime.second from t
datetime | id
-----------------------| -----
2020.01.01T00:00:00.000| 1 2 3
2020.01.01T00:00:01.000| 1 2 3
2020.01.01T00:00:02.000| 1 2
2020.01.01T00:00:03.000| 1 2
2020.01.01T00:00:04.000| 1 2
...
这将通过使用 .second
仅取秒组件来获得 entrytime 和 deletetime 之间的时间差。然后使用 "j"$
将其转换为 long 将得到一个可以使用 til each
的数字。最后,使用 "v"$
转换回第二种类型并将原始入口时间添加到这些列表中将创建一个秒列表,每个 id 的活动时间为:
q)select id,datetime:entrytime+"v"$til each"j"$deletetime.second-entrytime.second from t
id datetime ..
-----------------------------------------------------------------------------..
1 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 2020.01.01T00:00:02.000 20..
2 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 2020.01.01T00:00:02.000 20..
3 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 ..
最后,使用 ungroup 将取消 datetime 列的分组,然后立即在 datetime 列上使用 xgroup 将对那一秒处于活动状态的 ID 进行分组。
我在kdb有一个订单table,里面有订单id,订单输入时间和订单删除时间,如下图:
+----+-------------------------+-------------------------+
| id | entrytime | deletetime |
+----+-------------------------+-------------------------+
| 1 | 2020.01.01T00:00:00.000 | 2020.01.01T04:00:00.000 |
| 2 | 2020.01.01T00:00:00.000 | 2020.01.01T03:59:58.000 |
| 3 | 2020.01.01T00:00:00.000 | 2020.01.01T00:00:02.000 |
|... | ... | ... |
+----+-------------------------+-------------------------+
我想将其转换为每秒显示 open/active 个订单的视图,如下所示:
+-------------------------+---------+
| datetime | openids |
+-------------------------+---------+
| 2020.01.01T00:00:00.000 | 1 2 3 |
| 2020.01.01T00:00:01.000 | 1 2 3 |
| 2020.01.01T00:00:02.000 | 1 2 |
| 2020.01.01T00:00:03.000 | 1 2 |
| ... | ... |
| 2020.01.01T03:59:57.000 | 1 2 |
| 2020.01.01T03:59:58.000 | 1 |
| 2020.01.01T03:59:59.000 | 1 |
| 2020.01.01T04:00:00.000 | |
+-------------------------+---------+
我需要的是相当于
SELECT * FROM table1 LEFT JOIN ON datetime >= entrytime and datetime < deletetime
在 kdb 中。
我已经尝试 window 加入但收效甚微。
非常感谢任何帮助。
有很多选择可以做到这一点。请看下面的其中一个。
但首先我会将时间转换为 timestamp
类型,datetime
很难处理并且被认为已过时。
t: ([] id: 1 2 3
; entrytime: 3#2020.01.01D
; deletetime: 2020.01.01D04:00:00 2020.01.01D03:59:58 2020.01.01D00:00:02);
t: update datetime: {x+00:00:01*til `inte-9*y-x}'[entrytime;deletetime] from t;
t: ungroup t;
t: select openid: id by datetime from t;
timetable: ([]datetime: {x+00:00:01*til 2+`inte-9*y-x} . value exec min datetime
, max datetime from t);
t: timetable lj t;
t
解释:
- 将日期时间列添加到 table
t
以一秒钟的步骤跟踪所有可用订单的时间 ungroup
tablet
获取id<->可用时间映射- 按可用时间分组 table
t
。这已经给出了您正在寻找的结果。但是在没有可用订单的时候可能会有空档 - 通过加入
timetable
填补空白,其中所有时间都在订单的 create/delete 时间范围内,tablet
.
可以在不使用任何类型的连接的情况下在一行中完成此操作:
q)`datetime xgroup ungroup select id,datetime:entrytime+"v"$til each"j"$deletetime.second-entrytime.second from t
datetime | id
-----------------------| -----
2020.01.01T00:00:00.000| 1 2 3
2020.01.01T00:00:01.000| 1 2 3
2020.01.01T00:00:02.000| 1 2
2020.01.01T00:00:03.000| 1 2
2020.01.01T00:00:04.000| 1 2
...
这将通过使用 .second
仅取秒组件来获得 entrytime 和 deletetime 之间的时间差。然后使用 "j"$
将其转换为 long 将得到一个可以使用 til each
的数字。最后,使用 "v"$
转换回第二种类型并将原始入口时间添加到这些列表中将创建一个秒列表,每个 id 的活动时间为:
q)select id,datetime:entrytime+"v"$til each"j"$deletetime.second-entrytime.second from t
id datetime ..
-----------------------------------------------------------------------------..
1 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 2020.01.01T00:00:02.000 20..
2 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 2020.01.01T00:00:02.000 20..
3 2020.01.01T00:00:00.000 2020.01.01T00:00:01.000 ..
最后,使用 ungroup 将取消 datetime 列的分组,然后立即在 datetime 列上使用 xgroup 将对那一秒处于活动状态的 ID 进行分组。