【问题标题】:KDB/Q: Cannot create a column storing lists in a KDB tableKDB/Q:无法在 KDB 表中创建存储列表的列
【发布时间】:2026-01-18 12:25:01
【问题描述】:

我是 KDB 和 Q 的新手。

我在Q For Mortals 中阅读了以下内容,并推断 KDB 支持复合列。

在 kdb+ 中专门处理所有项都是相同类型的简单列表的嵌套列的情况。我们称之为复合列。不要求简单列表都具有相同的长度。

我知道可以在表中创建一个新列,如下所示:tablename: update newcol:value from tablename

当我将 value 设置为另一列或使用其他列或常量值进行某些计算时,它工作正常,并且在表中创建了一个新列,并设置了适当的值。但是,当我尝试将值设置为列表时,它不起作用:tablename: update newcol: (1 2) from tablename 给出“长度”错误。

我浏览了 Q For Mortals 中的文档,但无法弄清楚如何创建这样的复合列。请帮我创建一个存储列表的列。谢谢!

【问题讨论】:

    标签: database kdb


    【解决方案1】:

    没有看到示例,这很可能是因为 q 试图使用 1 2 作为 newcol 的值,它与表的长度不同。要将列表本身强制作为表中的每个条目,您需要具有适当数量的值。您可以使用虚拟列ienlist 来实现这一点。

    q)tab:([]time:5#.z.d;col1:1 2 3 4 5)
    q)tab
    time       col1
    ---------------
    2020.07.17 1
    2020.07.17 2
    2020.07.17 3
    2020.07.17 4
    2020.07.17 5
    q)update col2:1 2 from tab
    'length
    q)show tab:update col2:count[i]#enlist 1 2 from tab
    time       col1 col2
    --------------------
    2020.07.17 1    1 2
    2020.07.17 2    1 2
    2020.07.17 3    1 2
    2020.07.17 4    1 2
    2020.07.17 5    1 2
    q)meta tab
    c   | t f a
    ----| -----
    time| d
    col1| j
    col2| J
    

    表的meta包含col2的大写J,表示每个条目是一个long列表。

    【讨论】:

    • 假设我以这种方式使用 enlist 创建 col2。现在,如果我想将 col2 中的列表更改为另一个列表,例如 (2 1) 记录的子集,假设 col1 = 1、3 和 5 的列表。那么我将如何去做呢?
    • 您可以通过类似的方式执行此操作,但还可以在更新语句中包含 where 子句,如下所示:update col2:count[i]#enlist 2 1 from tab where col1 in 1 3 5 注意此命令假定您已经使用答案中概述的方法创建了 col2以上
    【解决方案2】:

    以 Q For Mortals 中的例子为例:

    q)tm:([] wk:2015.01.01 2015.01.08; rv:(38.92 67.34; 16.99 5.14 128.23 31.69))
    

    我们可以向其中添加另一个新的复合列,如下所示:

    q)update newcol:(1 2;3 4 5) from tm
    wk         rv                      newcol
    -----------------------------------------
    2015.01.01 38.92 67.34             1 2
    2015.01.08 16.99 5.14 128.23 31.69 3 4 5
    

    请注意,如果添加不同数量的行,例如由于不匹配导致的长度错误,例如在下面添加三行(或列表)

    q)update newcol:(1 2;3 4 5;6 7 8) from tm
    'length
      [0]  update newcol:(1 2;3 4 5;6 7 8) from tm
    

    【讨论】:

      【解决方案3】:

      给定一些表格

      q)show tab:([]a:10?`AAA`BBB`CCC;b:10?10000);
      a   b
      --------
      CCC 627
      CCC 2685
      BBB 1518
      BBB 725
      CCC 1369
      CCC 663
      BBB 9478
      BBB 1588
      AAA 8660
      CCC 3780
      

      如果你想添加一个常量复合列比如1 2你需要先扩展这个向量到表格的长度

      q)count[tab]#enlist 1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      1 2
      q)update c:count[tab]#enlist 1 2 from tab
      a   b    c
      ------------
      CCC 627  1 2
      CCC 2685 1 2
      BBB 1518 1 2
      BBB 725  1 2
      CCC 1369 1 2
      CCC 663  1 2
      BBB 9478 1 2
      BBB 1588 1 2
      AAA 8660 1 2
      CCC 3780 1 2
      

      生成复合列的其他常见方式是我们将符号字段更新为字符串时

      q)update string a from tab
      a     b
      ----------
      "CCC" 627
      "CCC" 2685
      "BBB" 1518
      "BBB" 725
      "CCC" 1369
      "CCC" 663
      "BBB" 9478
      "BBB" 1588
      "AAA" 8660
      "CCC" 3780
      

      或者在执行带有 by 子句但没有聚合的查询时

      q)select b by a from tab
      a  | b
      ---| ----------------------
      AAA| ,8660
      BBB| 1518 725 9478 1588
      CCC| 627 2685 1369 663 3780
      

      【讨论】: