我有一个包含date
字段datetime
的大表。作为输入两个datetime
列表afroms
和atos
列表的函数的一部分,我想为这些afrom,ato
对中的每一对计算所有日期在它们之间的大表的行。
我制定了一种不太有效的方法,即它具有严重的可扩展性缺点:
/ t1 contains my afrom,ato pairs
q)t1:([] afrom:`datetime$(2017.10.01T10:00:00.000 2017.10.02T10:00:00.000);ato:`datetime$(2017.10.01T12:00:00.000 2017.10.02T12:00:00.000));
q)t1
afrom ato
-----------------------------------------------
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000
2017.10.02T10:00:00.000 2017.10.02T12:00:00.000
/ t2 contains my very very large dataset
q)t2:([] date:`datetime$(2017.10.01T10:01:00.000 2017.10.01T10:02:00.000 2017.10.01T10:03:00.000 2017.10.02T10:01:00.000 2017.10.02T10:02:00.000 2017.10.02T10:03:00.000); ccypair:(3#`EURUSD),(3#`USDCHF); mid:6?1.05);
q)t2
date ccypair mid
----------------------------------------------------
2017.10.01T10:01:00.000 EURUSD 0.24256133290473372
2017.10.01T10:02:00.000 EURUSD 0.091602176288142809
2017.10.01T10:03:00.000 EURUSD 0.10756538207642735
2017.10.02T10:01:00.000 USDCHF 0.91046513157198206
2017.10.02T10:02:00.000 USDCHF 0.76424539103172717
2017.10.02T10:03:00.000 USDCHF 0.17090452200500295
然后我可以像这样使用cross
:
select from (t1 cross t2) where afrom<date,date<ato
这会产生正确的结果:
afrom ato date ccypa..
-----------------------------------------------------------------------------..
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000 2017.10.01T10:01:00.000 EURUS..
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000 2017.10.01T10:02:00.000 EURUS..
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000 2017.10.01T10:03:00.000 EURUS..
2017.10.02T10:00:00.000 2017.10.02T12:00:00.000 2017.10.02T10:01:00.000 USDCH..
2017.10.02T10:00:00.000 2017.10.02T12:00:00.000 2017.10.02T10:02:00.000 USDCH..
2017.10.02T10:00:00.000 2017.10.02T12:00:00.000 2017.10.02T10:03:00.000 USDCH..
但是,当我有大量afroms
和atos
列表时,cross
将“不必要地”扩展可能较大的表t2
倍{{1}并且这不能很好地扩展。
有更好的方法吗?例如我尝试过这样的事情:
t1
我需要做一个循环我猜但不知道如何。子问题..是否有可能有一个间隔元组的单一列表,即select from t2 where (exec afrom from t1)<date,date<(exec ato from t1)
error: `length
而不是分开intervals(afrom;ato)
和afroms
?
答案 0 :(得分:1)
如果我理解正确,那么执行此操作的一种方法是使用t1
的每一行,并找到每个时间范围内任何行落在within
的位置:
select from t2 where any date within/:value each t1
date ccypair mid
-----------------------------------------
2017.10.01T10:01:00.000 EURUSD 0.41239
2017.10.01T10:02:00.000 EURUSD 0.5429457
...
与上面的yoru示例输出相同,没有afrom
和ato
列。在此示例中,选择范围内的所有值,any
和每个右/:
允许您使用多个范围。如果这不适合您,那么您可以单独处理t1
的每一行:
raze{[x;y]select from x where date within value y}[t2]'[t1]
如果窗户不重叠,哪个应该有用。
如果您需要独占或者您可以尝试稍微修改窗口时间以确保它们被排除在外:
q)select from t2 where any date within/:value each @[t1;`afrom`ato;+;1 -1*00:00:00.001]
date ccypair mid
-----------------------------------------
2017.10.01T10:01:00.000 EURUSD 0.41239
2017.10.01T10:02:00.000 EURUSD 0.5429457
...
要将afrom
和ato
列添加到输出中,您可以使用所选行交叉它们:
raze{[x;y]flip[1#'y]cross select from x where date within value[y]+1 -1*00:00:00.001}[t2]'[t1]
afrom ato date ccypair mid
-----------------------------------------------------------------------------------------
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000 2017.10.01T10:01:00.000 EURUSD 0.41239
2017.10.01T10:00:00.000 2017.10.01T12:00:00.000 2017.10.01T10:02:00.000 EURUSD 0.5429457
...