功能更新 - 具有动态列的多变量函数

Functional update - multivariable function with dynamic columns

如能提供以下帮助,我们将不胜感激!

我有两个 table:table1 是摘要 table 而 table2 是所有数据点的列表。我希望能够为 table1.

中的每一行汇总 table2 中的信息
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;

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

table1 中,我想用类别名称(cl1cl2 等)命名一个新列,并且我希望该列中的值是运行 该列上的函数的输出。

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

`cl1`cl2`cl3

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

不过,下面应该会更有用、更快捷、更整洁:

您的问题可以分为两部分。对于第一部分,您希望通过 grp 和约束在 table2 内创建每个类别的总和。至于第二部分,您希望将这些结果(查找)加入 table1.

中的相应记录

您可以使用 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 查询

中创建列的嵌套列表

接下来是 cat 组中的 sum each

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

然后,要创建猫的列,您可以使用类似枢轴的语法 - 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

现在您可以使用此查找 table 并为 table1

中的每一行编制索引
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

加入从 table1 到结果的每一行
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

HTH,肖恩

坚持你的方法,你只需要让你的更新语句起作用,然后像这样迭代列:

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

假设您可以就地修改表 1。如果一定要保留原来的table1那么可以传值,虽然会消耗更多的内存

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

另一种方法是聚合、旋转和连接,尽管它不一定是更好的解决方案,因为您得到的是空值而不是零

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

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

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