【问题标题】:KDB windowed join with aggregation function on columns from both tablesKDB 窗口化联接,在两个表的列上具有聚合功能
【发布时间】:2019-09-10 00:10:39
【问题描述】:

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

假设我有一个表 A,其中包含 bucket_start_date、bucket_end_date 列

A
bucket_start_date | bucket_end_date
2015.05.02        | 2015.05.08
2015.05.08        | 2015.05.12

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

A
date        | coins
2015.05.02  | 5
2015.05.06  | 11     
2015.05.09  | 32

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

select A.bucket_start_date, A.bucket_end_date, sum((B.date - A.bucket_start_date) * B.coins) from A join B where B.date BETWEEN A.bucket_start_date and A.bucket_end_date group by A.bucket_start_date, A.bucket_end_date

我想要的是一列按开始日期的距离加权的硬币加权总和,而不是简单的列总和。即距离 bucket_start_date 较近的硬币在总和中的权重低于距离 bucket_start_date 较远的硬币。

wj1 的文档只讨论了第二张表上的聚合列,我如何编写一个聚合函数,同时考虑到连接的第一张表中的字段。

【问题讨论】:

    标签: kdb


    【解决方案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 表的日期列的日期。还可以使用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
    

    您可以重新排序选择语句中的操作以避免需要括号!

    编辑:

    为了回答您的后续问题,我修改了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 关键字快速将long 转换为布尔值。在这种情况下,not 将返回 1b 为每个 long 为 0,0b 为每个非零 long。

    【讨论】:

    • 如果在给定范围内没有来自 B 的条目,我会在日期列中得到类似 long$() in the coins column and date$() 的内容。我如何匹配这些条目? AKA 我如何查询上表中硬币列表为空列表的所有行
    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 2021-12-11
    • 2015-11-03
    相关资源
    最近更新 更多