2016-09-21 46 views
5

chcę uruchomić SQL konwencjonalnego stylu lewo przyłączyć KDB +/Q.Jak wykonać wydajne lewe sprzężenie w kdb?

  • Otrzymujemy co najmniej jeden wiersz w wyniku dla każdego wiersza w lewej tabeli.
  • Jeśli istnieje więcej niż jeden mecz w prawej tabeli, pojawia się wiersz dla każdy z nich, a nie tylko dla pierwszego meczu

danych testowych

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

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

Najlepszym Wersja, którą mogę wymyślić, wygląda tak:

To dołącza lewe połączenie, które zapewnia tylko pierwsze dopasowanie z łączeniem wewnętrznym, które zapewnia wszystkie dopasowania, a następnie usuwa duplikaty:

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

Czy ktoś może dać mi taki, który jest szybszy i/lub lepiej w jakimś inny sposób? Naprawdę chciałbym na przykład uniknąć użycia wyraźnych.

Odpowiedz

0

Opierając się na odpowiedzi @ Ryana.

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

Wow, dzięki! Connor, nie czytam jeszcze k. ** Czy możesz wyjaśnić, co zrobiłeś? ** Jeszcze raz dziękuję! – JSLover

+0

To jest q implementacja. 'q) nungroup: {$ [liczba x: 0!x;,/[przerzuć każdy x], najpierw każdy,/[x]; x]} ' –

+0

@Connor Gervin: twoje rozwiązanie daje błędne wyniki dla np. '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 

Zapewniamy darmowy poradnik na KDB dołącza który demonstruje wszystkie z nich tutaj: http://www.timestored.com/kdb-guides/qsql-inner-left-joins

Ponieważ chcemy każdy row..based na rozwiązanie @Connors

Nicea rozwiązanie Connor. I zmodyfikowane swoje skrócić/uprościć kod:

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: Connors jest szybsza i zużywa mniej pamięci w tym konkretnym przypadku.

+0

Czy spełnia on pierwsze wymaganie (otrzymujemy co najmniej jeden wiersz w wyniku dla każdego wiersza w lewej tabeli)? Sądzę, że OP chce, aby "3 6 0N" było uwzględnione w wyniku. –

+2

Dzięki za pomoc! Po prawej, potrzebujemy co najmniej jednego wiersza w wyniku dla każdego wiersza w lewej tabeli. Podpowiedź rozgrupowania/xgroup zawsze powoduje wewnętrzne sprzężenie, nawet jeśli używana jest operacja kdb "lj". Wynika to z tego, że puste wiersze utworzone przez lewe połączenie w zgrupowanej tabeli zawierają listy zerowej długości dla kolumn z tabeli niezgodnej. Gdy są one rozgrupowane, tworzą zero wierszy zamiast pojedynczego wiersza zawierającego puste pozycje. Czy ma sens mieć wersję rozgrupowania, która powoduje utworzenie pojedynczego wiersza z wartością null, gdy kolumny z wartościami na liście mają zerową długość? Tx! – JSLover

+0

Więc teraz uważam, że robię coś, co według mnie jest prawdopodobnie bardzo złą formą. Unikałem używania ciągów. Robię to, ponieważ struny, tak jak ja ich używam, przełamują proponowane tu podejście. Na przykład, uruchom ponownie rozwiązanie z nową wartością x z kolumną łańcuchową, gdy rozwiązanie się nie powiedzie. x: ([]; a: 1 1 2 3; b: 3 4 5 6; z: ("foo", "bar", "baz", "bang")) – JSLover