2016-09-21 35 views
5

我想運行一個常規的SQL風格左加入KDB +/Q.如何在kdb中執行高效的左連接?

  • 我們得到的結果至少一行在離開 表的每一行。
  • 如果右表中的一個以上的比賽,我得到一排 每個那些,不只是第一場比賽

測試數據

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

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

最好我可以想到的版本是這樣的:

這附加一個左連接,它只提供第一個匹配的內部連接,它提供所有匹配,然後刪除重複項:

distinct ej[`a; x; y] , x lj `a xkey y 

誰能爲我提供一個在某些 其他方式更快和/或更好?例如,我真的很想避免使用不同的字體。

回答

0

建立在@ Ryan的答案。

k)nungroup:{$[#x:0!x;(,/){$[#t:+:x;t;enlist *:'[x];t]}'[x]]} 
q)nungroup:{$[count x:0!x;(,/){$[count t:flip x;t;enlist first'[x]]}'[x];x]} 

q)nungroup x lj ` \`a xgroup y 

a b c 
----- 
1 3 7 
1 4 7 
2 5 8 
2 5 9 
3 6 
+0

哇,謝謝! Connor,我還沒有讀k。 **你能解釋一下你做了什麼嗎?** 再次感謝! – JSLover

+0

這是q實現。 'q)nungroup:{$ [count x:0!x;,/ [翻轉每個x],首先每個,/ [x]; x]}' –

+0

@Connor Gervin:您的解決方案給出錯誤的結果。 'x:([] a:1 1 2 3 4; b:3 4 5 6 100)' –

1
q)`a xgroup y // group the lookup table by keys 
a| c 
-| --- 
1| ,7 
2| 8 9 
4| ,10 
q)x lj `a xgroup y // join all combinations 
a b c 
------------ 
1 3 ,7 
1 4 ,7 
2 5 8 9 
3 6 `long$() 
q)ungroup x lj `a xgroup y // unroll using ungroup to produce a flat table 
a b c 
----- 
1 3 7 
1 4 7 
2 5 8 
2 5 9 

我們提供KDB免費加入教程演示所有的人都在這裏:http://www.timestored.com/kdb-guides/qsql-inner-left-joins

因爲我們希望在@Connors解決方案

很好的解決方案康納每row..based。我修改了您的代碼以縮短/簡化代碼:

q)bungroup:{ungroup {$[0=count x;(),first x; x]}''[x]} 
q)bungroup x lj `a xgroup y 
a b c 
-------- 
1 3 7 
1 4 7 
2 5 8 
2 5 9 
3 6 
4 100 10 

僅供參考:Connors更快,對這種特殊情況使用更少的內存。

+0

它是否符合第一個要求(我們在結果中左邊表格中的每一行至少得到一行)?我想OP希望把'3 6 0N'包括進去。 –

+2

感謝您的幫助! 對,我們在結果中至少需要一行左表中的每一行。 即使在使用kdb「lj」操作時,ungroup/xgroup技巧總是會導致內部連接。這是因爲組合表中左連接產生的空行包含來自不匹配表的列的零長度列表。當這些被取消分組時,它們產生零行而不是包含空條目的單行。 當列表值列的長度爲零時,生成一個具有空值的單行的ungroup版本是否合理? TX! – JSLover

+0

所以,現在我發現我自己在做一些我認爲可能是非常糟糕的形式。我避免使用字符串。我這樣做是因爲字符串,因爲我正在使用它們,打破了這裏提出的方法。例如,再次運行該解決方案,並使用字符串列的新值x解決方案失敗。 x:([]; a:1 1 2 3; b:3 4 5 6; z:(「foo」;「bar」;「baz」;「bang」)) – JSLover