【问题标题】:How to do a FULL OUTER JOIN in KDB?如何在 KDB 中进行 FULL OUTER JOIN?
【发布时间】:2014-10-27 11:39:00
【问题描述】:

我在 KDB 中有 2 个表 x,y

x:([a:1 1 2 3]; b:3 4 5 6)
q) a | b
   -----
   1 | 3
   1 | 4
   2 | 5
   3 | 6

y:([a:1 2 2 4]; c:7 8 9 10)
q) a |  c
   ------
   1 |  7
   2 |  8
   2 |  9
   4 | 10

我想做x FULL OUTER JOIN y ON x.a = y.a的SQL-equivalent,也就是我想要结果:

([a:1 1 2 2 3 4]; b:3 4 5 5 6 0N; c:7 7 8 9 0N 10)
q) a |   b   c
   -----------
   1 |   3   7
   1 |   4   7
   2 |   5   8
   2 |   5   9
   3 |   6 0Nj
   4 | 0Nj  10

KDB reference,我能找到的最接近的是uj,但没有给出我想要的:

x uj y
q) a |   b   c
   -----------
   1 |   3   7
   2 |   5   8
   3 |   6 0Nj
   4 | 0Nj  10

那么我将如何在 KDB 中创建 FULL OUTER JOIN

【问题讨论】:

    标签: join outer-join kdb


    【解决方案1】:

    这给出了您要求的结果

    q)`a xasc 1!distinct (uj). 0!/:lj'[(x;y);(y;x)]
    a| b c
    -| ----
    1| 3 7
    1| 4 7
    2| 5 8
    2| 5 9
    3| 6
    4|   10
    

    一切顺利, 格伦

    编辑:添加排序

    【讨论】:

      【解决方案2】:

      对于这样的 SQL 语句:

      从 x,y 中选择,其中 x.a=y.a

      您可以在 KDB 中使用等值连接动词 (http://code.kx.com/q/ref/joins/#ej-equi-join)。

      例如:如果我们将其应用于您的示例表

              q> ej[`a;x;y]
      

      输出:

      a b c

      1 3 7

      1 4 7

      2 5 8

      2 5 9

      要获得完全外连接,只需从表 x 和 y 中提取非公共键并将它们附加到等值连接结果中。

                   q> r,(0!x,'y) except r:ej[`a;x;y]
      

      这将为您提供所需的输出。

      【讨论】:

      • x,'y 如果 x 和 y 的长度不同,则会失败。我想你是想穿越
      • 这很好,但@JPC 有一点。但是,将 ,' 替换为 cross 并不总是相同(它会返回更多条目)。有没有办法解决这个问题?
      • 这不应该是公认的答案。它在没有执行适当的外连接的情况下过度拟合了 OP 提供的示例。
      【解决方案3】:

      退后一步,想想你想要什么,你拥有什么。

      你想要一个外连接,它是左连接(同上)和右连接(相当于左连接)的并集(在 q 中可用),所以让我们这样做:

      q)oj:{
          lxy:0!lj[x;y];                  // Left join (plus remove keys)
          lyx:(cols lxy) xcols 0!lj[y;x]; // Right join (plus remove keys 
                                          // and prepare cols order for union)
          (cols key x) lxy union lyx      // Union (plus retrieve keys)
          };
      
      q)oj[x;y]
      a| b c
      -| ----
      1| 3 7
      1| 4 7
      2| 5 8
      3| 6
      2| 5 9
      4|   10
      

      当然,您可以将其设置为不透明的单线以适应 q 社区:

      q)(cols key x) xkey ((cols lxy) xcols 0!lj[y;x]) union lxy:0!lj[x;y]
      a| b c
      -| ----
      1| 3 7
      2| 5 8
      2| 5 9
      4|   10
      1| 4 7
      3| 6
      

      警告:
      Union 假设它有两个集合,并将返回一个集合。这意味着如果两个输入之一中的两行相同,则它们将在oj 的输出中折叠为一。这是要记住的事情,尽管你给出的例子似乎并不关心它。

      【讨论】:

        猜你喜欢
        • 2021-09-06
        • 2022-08-30
        相关资源
        最近更新 更多