是否有更可扩展的子选择替代此查询?

时间:2017-12-06 10:09:37

标签: subquery kdb q-lang sql-subselect

我有一个包含date字段datetime的大表。作为输入两个datetime列表afromsatos列表的函数的一部分,我想为这些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..

但是,当我有大量afromsatos列表时,cross将“不必要地”扩展可能较大的表t2倍{{1}并且这不能很好地扩展。

有更好的方法吗?例如我尝试过这样的事情:

t1

我需要做一个循环我猜但不知道如何。子问题..是否有可能有一个间隔元组的单一列表,即select from t2 where (exec afrom from t1)<date,date<(exec ato from t1) error: `length 而不是分开intervals(afrom;ato)afroms

1 个答案:

答案 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示例输出相同,没有afromato列。在此示例中,选择范围内的所有值,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
...

要将afromato列添加到输出中,您可以使用所选行交叉它们:

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
...