kdb 如何在 select 中有一个条件和

kdb how to have a conditional sum in select

我怎样才能在 kdb 中有条件求和,类似于下面的 sql 查询

Select sum(qty > 0, qty, 0) as buy, sum(qty < 0, qty, 0) as sell from trades

我正在寻找一种无需任何 where 子句即可执行此操作的方法。

您可以在 select 语句中使用内联 lambda 函数来实现此目的:

q)trades:([]sym:`a`b`c`d`e`f`g;qty:-34 -27 -11 50 19 -30 1)
q)select buy:sum {x where 0<x}[qty], sell:sum {x where 0>x}[qty] from trades
buy sell
--------
70  -102

更好的方法(有条件):

q)select buy:sum ?[qty>0;qty;0], sell:sum ?[qty<0;qty;0] from trades
buy sell
--------
70  -102

使用 'min' 和 'max' 运算符:

q)select buy:sum qty|0f,sell:sum qty&0f from trades
buy sell
--------
70  -102

我会遵循@davidcrossey 提出的第一种方法,但会稍微简化代码并删除匿名函数:

select buy: sum qty where qty > 0, sell: sum qty where qty < 0 from trades

这个查询是可取的,因为 ?[;;] 工作更慢并且消耗更多 space (~ 2 次)。 min/max 方法可能更快,但也会消耗 x2 space。您可以使用下一个代码作为性能测试,\ts returns time space 被查询使用

trades: enlist[`qty]!enlist -50 + 1000000?100;
\ts select buy: sum qty where qty > 0, sell: sum qty where qty < 0 from trades
// returns 43 8389424
\ts select buy:sum ?[qty>0;qty;0], sell:sum ?[qty<0;qty;0] from     trades
// returns 68 17826560
\ts select buy:sum qty|0f,sell:sum qty&0f from trades
// returns 39 16777856

在这种情况下,< & > 充当向量条件运算符,因此传递完整的列有效。 但是,有些情况下函数需要输入作为原子,在这种情况下,可以使用 each

q)trades:([]sym:`a`b`c`d`e`f`g;qty:-34 -27 -11 50 19 -30 1)
q)select buy:sum qty where {0<x}each qty, sell:sum qty where {0>x} each qty from trades
buy sell
--------
70  -102

您现在可以将 {0<x} 替换为一些以原子为参数的更复杂的函数,它应该可以正常工作。