代码之家  ›  专栏  ›  技术社区  ›  amandath

函数更新-带动态列的多变量函数

kdb
  •  3
  • amandath  · 技术社区  · 6 年前

    如果您在以下方面有任何帮助,我们将不胜感激!

    我有两张桌子: table1 是一个汇总表 table2 是所有数据点的列表。我希望能够在 表2 对于中的每一行 表1

    table1:flip `grp`constraint!(`a`b`c`d; 10 10 20 20);
    table2:flip `grp`cat`constraint`val!(`a`a`a`a`a`b`b`b;`cl1`cl1`cl1`cl2`cl2`cl2`cl2`cl1; 10 10 10 10 10 10 20 10; 1 2 3 4 5 6 7 8);
    
    function:{[grpL;constraintL;catL] first exec total: sum val from table2 where constraint=constraintL, grp=grpL,cat=catL};
    
    update cl1:function'[grp;constraint;`cl1], cl2:function'[grp;constraint;`cl2] from table1;
    

    这段代码的第四行实现了我想要的两个类别: cl1 cl2

    在里面 表1 我想用类别的名称命名一个新列( cl1级 , cl2 ,我希望该列中的值是在该列上运行函数的输出。

    然而,我有数百个不同的类别,所以不想像第四行那样手动列出它们。我如何传递类别列表,例如下面的?

    `cl1`cl2`cl3
    
    3 回复  |  直到 6 年前
        1
  •  5
  •   terrylynch    6 年前

    按照您的方法,您只需使update语句起作用,然后像这样迭代列:

    {![`table1;();0b;(1#x)!enlist ((';function);`grp;`constraint;1#x)]} each `cl1`cl2
    

    假设您可以修改表1。如果必须保留原始表1,则可以按值传递它,尽管它会消耗更多内存

    {![x;();0b;(1#y)!enlist ((';function);`grp;`constraint;1#y)]}/[table1;`cl1`cl2]
    

    另一种方法是聚合、透视和连接,尽管这不一定是一个更好的解决方案,因为您得到的是null而不是零

    a:select sum val by cat,grp,constraint from table2
    p:exec (exec distinct cat from a)#cat!val by grp,constraint from a
    table1 lj p
    
        2
  •  3
  •   Sean O'Hagan Rahul    6 年前

    您可以研究几种不同的方法。 最简单的方法是功能更新- http://code.kx.com/wiki/JB:QforMortals2/queries_q_sql#Functional_update

    不过,下面的内容应该更有用、更快、更整洁:

    你的问题可以分为两部分。对于第一部分,您希望在表2中通过grp和约束创建每个类别的总和。至于第二部分,您希望将这些结果(查找)连接到表1中的相应记录上。

    您可以使用创建必要的组 by

    q)exec val,cat by grp,constraint from table2
    grp constraint| val       cat
    --------------| ------------------------------
    a   10        | 1 2 3 4 5 `cl1`cl1`cl1`cl2`cl2
    b   10        | 6 8       `cl2`cl1
    b   20        | ,7        ,`cl2
    

    但请注意,这只会在select查询中创建列的嵌套列表

    下一步是 sum each cat “组”

    q)exec sum each val group cat by grp,constraint from table2
    grp constraint|
    --------------| ------------
    a   10        | `cl1`cl2!6 9
    b   10        | `cl2`cl1!6 8
    b   20        | (,`cl2)!,7
    

    然后,要创建cat列,可以使用类似pivot的语法- http://code.kx.com/wiki/Pivot

    q)cats:asc exec distinct cat from table2
    q)exec cats#sum each val group cat by grp,constraint from table2
    grp constraint| cl1 cl2
    --------------| -------
    a   10        | 6   9
    b   10        | 8   6
    b   20        |     7
    

    现在,您可以使用此查找表并索引到表1中的每一行

    q)(exec cats#sum each val group cat by grp,constraint from table2)[table1]
    cl1 cl2
    -------
    6   9
    8   6
    

    要用零填充空值,请使用克拉符号- http://code.kx.com/wiki/Reference/Caret

    q)0^(exec cats#sum each val group cat by grp,constraint from table2)[table1]
    cl1 cl2
    -------
    6   9
    8   6
    0   0
    0   0
    

    现在,您可以使用 join-each

    q)table1,'0^(exec cats#sum each val group cat by grp,constraint from table2)[table1]
    grp constraint cl1 cl2
    ----------------------
    a   10         6   9
    b   10         8   6
    c   20         0   0
    d   20         0   0
    

    嗯,肖恩

        3
  •  -1
  •   Karan Patel    6 年前

    这种方法是传递类别列表的最简单方法

    {table1^flip x!function'[table1`grp;table1`constraint;]each x}`cl1`cl2