在两个表的列上均具有聚合功能的KDB窗口式联接

时间:2019-09-10 00:10:39

标签: kdb

这是对How to do a between join clause in KDB?的扩展问题

假设我有一个表A,其中的列bucket_start_date,bucket_end_date,

df=['Apple sauce','Banana & peach','c(&)a']

df.columns = df.columns.str.lower()
df.columns = df.columns.str.replace(' ', '')
df.columns = df.columns.str.replace('&','') 
df.columns = df.columns.str.replace('(','')
df.columns = df.columns.str.replace(')','')

Desired Out: df=['applesauce','bananapeach','ca']

还假设我有一个表B,其中列有日期,硬币。

A
bucket_start_date | bucket_end_date
2015.05.02        | 2015.05.08
2015.05.08        | 2015.05.12

如何在逻辑上看起来像kdb的联接

从A连接B中选择A.bucket_start_date,A.bucket_end_date,sum((B.date-A.bucket_start_date)* B.coins),其中B.date在A.bucket_start_date和A.bucket_end_date之间按A.bucket_start_date分组, A.bucket_end_date

我想要的是一列硬币的加权总和,该硬币的总和由开始日期的距离加权,而不是一列简单的总和。距离bucket_start_date最近的Aka硬币的权重要比远离bucket_start_date远的硬币的权重低。

wj1的文档仅讨论第二个表上的聚合列,我该如何编写一个聚合函数,还要考虑联接的第一个表中的字段。

1 个答案:

答案 0 :(得分:1)

您可以通过在日期列上添加其他聚合函数来修改上一个问题的窗口联接,如下所示:

q)show w:wj1[A`bucket_start_date`bucket_end_date;`date;A;(B;(sum;`coins);(::;`date))]
bucket_start_date bucket_end_date coins date
-------------------------------------------------------------
2015.05.02        2015.05.08      16    2015.05.02 2015.05.06
2015.05.08        2015.05.12      32    ,2015.05.09
q)show w:ungroup w
bucket_start_date bucket_end_date coins date
--------------------------------------------------
2015.05.02        2015.05.08      16    2015.05.02
2015.05.02        2015.05.08      16    2015.05.06
2015.05.08        2015.05.12      32    2015.05.09

在窗口连接的最后,您可以添加标识函数(::),该函数将简单地输出输入,在这种情况下,该函数是B表中date列的日期,该日期位于相应窗口内。还可以使用ungroup关键字“分解”表,以使此新日期列不是日期列表。

使用此表w,一条select语句(非常类似于您提供的语句)可以得到硬币的加权总和:

q)select sum coins*date-bucket_start_date by bucket_start_date,bucket_end_date from w
bucket_start_date bucket_end_date| coins
---------------------------------| -----
2015.05.02        2015.05.08     | 64
2015.05.08        2015.05.12     | 32

您可以在select语句中对操作进行重新排序,以避免使用括号!

编辑:

为回答您的问题,我修改了wj1以获得与您的问题类似的表格:

q)t:wj1[A`bucket_start_date`bucket_end_date;`date;A;(B;(::;`coins);(::;`date))]
q)t
bucket_start_date bucket_end_date coins    date
----------------------------------------------------------------
2015.05.02        2015.05.08      5 11     2015.05.02 2015.05.06
2015.05.08        2015.05.12      ,32      ,2015.05.09
2015.05.12        2015.05.18      `long$() `date$()

选择空行的一种方法是对每一行进行计数并取所有计数为0的行:

q)select from t where not count each coins
bucket_start_date bucket_end_date coins date
--------------------------------------------
2015.05.12        2015.05.18

我们可以通过逐步分解来查看where子句的作用:

q)t`coins
5 11
,32
`long$()
q)count each t`coins
2 1 0
q)not count each t`coins
001b

最后一行使用not关键字,将长型转换为布尔型的快速方法。在这种情况下,not将为每个长度为0的1b和每个非零长度的0b返回。