【问题标题】:kdb - functional update where multiple columns from table A match multiple columns from table Bkdb - 表 A 中的多个列与表 B 中的多个列匹配的功能更新
【发布时间】:2020-04-03 20:00:23
【问题描述】:

我有以下 2 个示例表。我想把下面的q-sql语句变成功能更新...

A:([]orderID:`Aa`Bb`Cc`Bb`Bb`Cc`Aa; date:2016.10.26 2004.09.30 2004.03.10 2016.11.08 2004.02.14 2010.06.01 2008.05.01; number:9 4 5 4 2 7 8; name:`Emp1`Emp2`Emp3`Emp2`Emp2`Emp3`Emp1; cost:100.7 99.8 84.2 85.5 73.9 91.6 94.1; ID:0 1 1 0 1 1 1)

B:([]oid:`Aa`Dd`Cc`Ee`Bb`Cc`Aa; dte:2009.10.26 2020.04.04 2020.03.06 2006.09.28 2004.02.14 2019.09.27 2012.04.30; num:9 5 7 8 2 6 1; nme:`Emp1`Emp2`Emp1`Emp2`Emp2`Emp4`Emp1; cst:100.7 69.8 74.2 85.5 73.9 81.6 94.1; ID:5 5 7 5 7 5 5)

update ID:5 from A where {[a;b;c;d;e]a,b,c,d,e}'[orderID;date;number;name;cost] in (exec {[a;b;c;d;e]a,b,c,d,e}'[oid;dte;num;nme;cst] from B where ID=5)

如果我对其进行解析,我会收到以下信息...

!
`A
,,(in;((';{[a;b;c;d;e]a,b,c,d,e});`orderID;`date;`number;`name;`cost);(?;`B;,,(=;`ID;5);();,((';{[a;b;c;d;e]a,b,c,d,e});`oid;`dte;`num;`nme;`cst)))
0b
(,`ID)!,5

如何翻译此处的k constraint 语句以在功能更新中工作?

我尝试了以下方法,但检查时没有更新任何结果...

![`A;enlist(in;((';{[a;b;c;d;e]a,b,c,d,e});`orderID;`date;`number;`name;`cost);(?[`B;enlist(=;`ID;5);();enlist enlist((';{[a;b;c;d;e]a,b,c,d,e});`oid;`dte;`num;`nme;`cst)]));0b;(enlist`ID)!enlist 5i]

如果orderID, date, number, name, cost 匹配来自table Boid, dte, num, nme, cst 的值,我的目标是更新table AID 列。如果没有,则保持原样。

首选输出如下所示...

q)A
orderID date       number name cost  ID
---------------------------------------
Aa      2016.10.26 9      Emp1 100.7 5
Bb      2004.09.30 4      Emp2 99.8  1
Cc      2004.03.10 5      Emp3 84.2  1
Bb      2016.11.08 4      Emp2 85.5  0
Bb      2004.02.14 2      Emp2 73.9  1
Cc      2010.06.01 7      Emp3 91.6  1
Aa      2008.05.01 8      Emp1 94.1  1

谢谢。

【问题讨论】:

  • 如果我们更了解您正在比较和更新的表格,我们可以更轻松地提供帮助。请提供代码 sn-p 来生成 A 和 B。了解您为什么希望这是函数语句也会很有帮助 - 您是否正在寻找一个可以采用 A 和 B 列名的函数?
  • @JorgeSawyer - 更新了上面的表格和 cmets。让我知道这是否有帮助。除了功能更新,我对其他解决方案持开放态度。虽然实际上我的表有数百万行,但我需要对解决方案进行功能化,以便用于更新我的 ID 列的值并不总是恒定的,例如从 B 的每一行获取 ID,如果必要的列值彼此相等,则将 A 的 ID 值更新为 B 的 ID 值。在这种情况下,我将执行 exec distinct ID from B 来获取每个值,然后将该列表传递给函数以在每个值上运行。

标签: kdb


【解决方案1】:

如果我理解正确,您希望更新A 中的ID 列的值,以便在其他列匹配时与B 中的值匹配。

这听起来更像是left join 的工作,而不是更新声明。鉴于您在上面生成的表格:

q)show A:([]orderID:`Aa`Bb`Cc`Bb`Bb`Cc`Aa; date:2016.10.26 2004.09.30 2004.03.10 2016.11.08 2004.02.14 2010.06.01 2008.05.01; number:9 4 5 4 2 7 8; name:`Emp1`Emp2`Emp3`Emp2`Emp2`Emp3`Emp1; cost:100.7 99.8 84.2 85.5 73.9 91.6 94.1; ID:0 1 1 0 1 1 1)
orderID date       number name cost  ID
---------------------------------------
Aa      2016.10.26 9      Emp1 100.7 0
Bb      2004.09.30 4      Emp2 99.8  1
Cc      2004.03.10 5      Emp3 84.2  1
Bb      2016.11.08 4      Emp2 85.5  0
Bb      2004.02.14 2      Emp2 73.9  1
Cc      2010.06.01 7      Emp3 91.6  1
Aa      2008.05.01 8      Emp1 94.1  1
q)show B:([]oid:`Aa`Dd`Cc`Ee`Bb`Cc`Aa; dte:2009.10.26 2020.04.04 2020.03.06 2006.09.28 2004.02.14 2019.09.27 2012.04.30; num:9 5 7 8 2 6 1; nme:`Emp1`Emp2`Emp1`Emp2`Emp2`Emp4`Emp1; cst:100.7 69.8 74.2 85.5 73.9 81.6 94.1; ID:5 5 7 5 7 5 5)
oid dte        num nme  cst   ID
--------------------------------
Aa  2009.10.26 9   Emp1 100.7 5
Dd  2020.04.04 5   Emp2 69.8  5
Cc  2020.03.06 7   Emp1 74.2  7
Ee  2006.09.28 8   Emp2 85.5  5
Bb  2004.02.14 2   Emp2 73.9  7
Cc  2019.09.27 6   Emp4 81.6  5
Aa  2012.04.30 1   Emp1 94.1  5

我看到A 中的第五行匹配B 中的一行,所以A 中的第五行应该更新为B 中的相应值:7。您可以使用左连接来像这样实现:

q)A lj 5!cols[A] xcol B
orderID date       number name cost  ID
---------------------------------------
Aa      2016.10.26 9      Emp1 100.7 0
Bb      2004.09.30 4      Emp2 99.8  1
Cc      2004.03.10 5      Emp3 84.2  1
Bb      2016.11.08 4      Emp2 85.5  0
Bb      2004.02.14 2      Emp2 73.9  7
Cc      2010.06.01 7      Emp3 91.6  1
Aa      2008.05.01 8      Emp1 94.1  1

简单解释一下:xcol 函数强制B 的模式与A 匹配,(!)enkey 运算符将前五列设置为键。最后,左连接执行您想要的更新。

如果您想一次只专注于更新一个 ID 值,您可以在左加入之前使用功能选择过滤 B:

A lj 5!cols[A] xcol ?[B;enlist(=;`ID;5);0b;()]

如果我误解了什么,请告诉我。您的输出表与我理解的您的目标不太匹配。第一列是否应该在 AB 中匹配?

【讨论】:

  • 谢谢@Jorge。这很有帮助。此外,用在table B 中不出现的 ID(例如 99)标记来自table A 的行的最佳方法是什么,即在上面的示例中,行 1 2 3 4 6 7(除5)。谢谢!
  • 幸运的是 in 关键字适用于表格行,因此您可以在这里利用它。 not (delete ID from A) in (delete ID from cols[A] xcol B) 会给你一个你想要更新的行的布尔向量,你可以将它输入到一个函数更新语句中。
【解决方案2】:
q)A:([]orderID:`Aa`Bb`Cc`Bb`Bb`Cc`Aa; date:2009.10.26 2004.09.30 2004.03.10 2016.11.08 2004.02.14 2010.06.01 2008.05.01; number:9 4 5 4 2 7 8; name:`Emp1`Emp2`Emp3`Emp2`Emp2`Emp3`Emp1; cost:100.7 99.8 84.2 85.5 73.9 91.6 94.1; ID:0 1 1 0 1 1 1)
q)A lj 5!cols[A] xcol select from B where ID=5
orderID date       number name cost  ID
---------------------------------------
Aa      2009.10.26 9      Emp1 100.7 5
Bb      2004.09.30 4      Emp2 99.8  1
Cc      2004.03.10 5      Emp3 84.2  1
Bb      2016.11.08 4      Emp2 85.5  0
Bb      2004.02.14 2      Emp2 73.9  1
Cc      2010.06.01 7      Emp3 91.6  1
Aa      2008.05.01 8      Emp1 94.1  1

【讨论】:

    猜你喜欢
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    相关资源
    最近更新 更多