2016-09-21 32 views
5

Tôi muốn chạy một SQL kiểu truyền thống còn lại tham gia vào KDB +/Q.Làm cách nào để thực hiện phép nối trái hiệu quả trong kdb?

  • Chúng tôi nhận được ít nhất một dòng trong kết quả cho mỗi dòng trong trái bảng.
  • Nếu có nhiều hơn một trận đấu ở bảng bên phải, tôi nhận được một hàng cho mỗi người, không chỉ cho trận đấu đầu tiên

dữ liệu thử nghiệm

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

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

tốt nhất phiên bản tôi có thể nghĩ ra như sau:

Điều này nối thêm một phép nối trái chỉ cung cấp kết quả khớp đầu tiên cho phép nối bên trong cung cấp tất cả các kết quả phù hợp và sau đó loại bỏ các bản sao:

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

Có ai có thể cung cấp cho tôi một cái nhanh hơn và/hoặc tốt hơn trong một số cách khác không? Tôi thực sự muốn tránh việc sử dụng riêng biệt, ví dụ.

Trả lời

0

Xây dựng câu trả lời của @ 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

Wow, cảm ơn! Connor, tôi chưa đọc k. ** Bạn có thể giải thích những gì bạn đã làm không? ** Cảm ơn bạn một lần nữa! – JSLover

+0

Đây là triển khai q. 'q) nhóm: {$ [count x: 0!x;,/[lật từng x], trước tiên,/[x]; x]} ' –

+0

@Connor Gervin: giải pháp của bạn cho kết quả sai cho ví dụ: '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 

Chúng tôi cung cấp một hướng dẫn miễn phí trên KDB tham gia thể hiện tất cả trong số họ ở đây: http://www.timestored.com/kdb-guides/qsql-inner-left-joins

Vì chúng ta muốn mọi row..based trên giải pháp @Connors

đẹp giải pháp Connor. Tôi đã sửa đổi của bạn để rút ngắn/đơn giản hóa mã:

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 nhanh hơn và sử dụng ít bộ nhớ hơn cho trường hợp cụ thể này.

+0

Ứng dụng có đáp ứng yêu cầu đầu tiên (Chúng tôi nhận được ít nhất một hàng trong kết quả cho mỗi hàng trong bảng bên trái) không? Tôi đoán OP muốn '3 6 0N' để được bao gồm nó kết quả. –

+2

Cảm ơn sự giúp đỡ! Phải, chúng tôi cần ít nhất một hàng trong kết quả cho mỗi hàng trong bảng bên trái. Bí quyết ungroup/xgroup luôn dẫn đến kết nối bên trong, ngay cả khi hoạt động kdb "lj" được sử dụng. Điều này là do các hàng rỗng được tạo ra bởi phép nối bên trái trên bảng được nhóm lại chứa các danh sách độ dài bằng không cho các cột từ bảng chưa được so khớp. Khi chúng không được nhóm lại, chúng tạo ra 0 hàng thay vì một hàng có chứa các mục rỗng. Sẽ có ý nghĩa khi có một phiên bản của ungroup tạo ra một hàng duy nhất có giá trị null khi danh sách có giá trị các cột có độ dài bằng không? Tx! – JSLover

+0

Vì vậy, bây giờ tôi thấy mình đang làm một cái gì đó mà tôi tin rằng có lẽ là hình thức thực sự xấu. Tôi tránh sử dụng dây. Tôi làm điều đó bởi vì dây, như tôi đang sử dụng chúng, phá vỡ cách tiếp cận được đề xuất ở đây. Ví dụ, chạy giải pháp một lần nữa với một giá trị mới của x với một cột chuỗi nó giải pháp không thành công. x: ([]; a: 1 1 2 3; b: 3 4 5 6; z: ("foo"; "bar"; "baz"; "bang")) – JSLover

Các vấn đề liên quan