2016-09-21 3 views
5

Я хочу запустить обычный SQL-стиль оставил присоединиться к KDB +/Q.Как выполнить эффективное левое соединение в kdb?

  • Мы получаем по крайней мере одну строку в результате для каждой строки в левой таблице.
  • Если есть больше чем один матч в таблице справа, я получаю строку для каждого из них, а не только для первого матча

Test Data

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

Основываясь на ответе Райана.

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

Вау, спасибо! Коннор, я еще не читаю. ** Можете ли вы объяснить, что вы сделали? ** Еще раз спасибо! – 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 

Мы предоставляем бесплатный учебник по КДБ присоединяется, который демонстрирует все из них здесь: http://www.timestored.com/kdb-guides/qsql-inner-left-joins

Поскольку мы хотим, чтобы каждый row..based на @Connors растворе

Nice решение Connor. Я изменил ваш, чтобы сократить/упростить код:

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 

FYI: Коннорс быстрее и использует меньше памяти для данного конкретного случая.

+0

Соответствует ли оно первому требованию (мы получаем по крайней мере одну строку в результате для каждой строки в левой таблице)? Я думаю, что OP хочет, чтобы «3 6 0N» включил его в результат. –

+2

Спасибо за помощь! Правильно, нам нужна хотя бы одна строка в результатах для каждой строки в левой таблице. Трюк ungroup/xgroup всегда приводит к внутреннему соединению, даже если используется операция kdb «lj». Это связано с тем, что нулевые строки, созданные левым соединением в сгруппированной таблице, содержат списки нулевой длины для столбцов из непревзойденной таблицы. Когда они негруппированы, они производят нулевые строки вместо одной строки, содержащей нулевые записи. Имеет ли смысл иметь версию ungroup, которая создает одну строку с нулевым значением, когда столбцы счисления имеют нулевую длину? Tx! – JSLover

+0

Итак, теперь я нахожу, что я сам делаю то, что, я считаю, вероятно, очень плохой. Я избегаю использования строк. Я делаю это, потому что строки, когда я их использую, нарушают предложенный здесь подход. Например, снова запустите решение с новым значением x со строковым столбцом, решение которого не выполняется. x: ([]; a: 1 1 2 3; b: 3 4 5 6; z: ("foo"; "bar"; "baz"; "bang")) – JSLover

 Смежные вопросы

  • Нет связанных вопросов^_^