是否有比此查询更具可扩展性的 sub-select 替代方案?
Is there a more scalable sub-select alternative to this query?
我有一个很大的 table,其中包含 date
类型的 datetime
字段。作为将 datetime
的两个列表作为输入的函数的一部分,即 afroms
和 atos
的列表,我想为每个 afrom,ato
对计算所有日期介于它们之间的大 table 行。
我想出一个不是很有效的方法来做到这一点,即它有一个严重的可扩展性缺陷:
/ 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
将 "unnecessarily" 扩展潜在的大 table t2
乘以 t1
的大小,并且不能很好地扩展。
有更好的方法吗?例如我试过类似的东西:
select from t2 where (exec afrom from t1)<date,date<(exec ato from t1)
error: `length
我想我需要做一个循环,但不确定如何做。子问题 .. 是否可以有一个间隔元组的单一列表,即 intervals(afrom;ato)
而不是分开 afroms
和 atos
?
如果我理解正确,那么一种方法是使用 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
列。在此示例中,within 选择范围内的所有值,any
和 each-right /:
允许您使用多个范围。如果这对您来说不是特别好,那么您可以单独处理 t1
的每一行:
raze{[x;y]select from x where date within value y}[t2]'[t1]
如果 windows 不重叠,哪个应该有效。
如果您需要独占,或者您可以尝试稍微修改 window 次以确保它们被排除在外:
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
...
我有一个很大的 table,其中包含 date
类型的 datetime
字段。作为将 datetime
的两个列表作为输入的函数的一部分,即 afroms
和 atos
的列表,我想为每个 afrom,ato
对计算所有日期介于它们之间的大 table 行。
我想出一个不是很有效的方法来做到这一点,即它有一个严重的可扩展性缺陷:
/ 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
将 "unnecessarily" 扩展潜在的大 table t2
乘以 t1
的大小,并且不能很好地扩展。
有更好的方法吗?例如我试过类似的东西:
select from t2 where (exec afrom from t1)<date,date<(exec ato from t1)
error: `length
我想我需要做一个循环,但不确定如何做。子问题 .. 是否可以有一个间隔元组的单一列表,即 intervals(afrom;ato)
而不是分开 afroms
和 atos
?
如果我理解正确,那么一种方法是使用 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
列。在此示例中,within 选择范围内的所有值,any
和 each-right /:
允许您使用多个范围。如果这对您来说不是特别好,那么您可以单独处理 t1
的每一行:
raze{[x;y]select from x where date within value y}[t2]'[t1]
如果 windows 不重叠,哪个应该有效。
如果您需要独占,或者您可以尝试稍微修改 window 次以确保它们被排除在外:
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
...