2016-09-26 80 views
2

在Apache的蜂巢我要表,我想離開,加入來自左數據保持所有數據和右表在可能添加數據。 爲此,我使用兩個連接,因爲連接基於兩個字段(一個material_id和一個location_id)。 這工作正常,有兩個傳統左聯接:蜂巢/ SQL - LEFT JOIN與後備

SELECT 
    a.*, 
    b.* 
FROM a 
INNER JOIN (some more complex select) b 
    ON a.material_id=b.material_id 
    AND a.location_id=b.location_id; 

對於LOCATION_ID數據庫只包含兩個不同的值,比如1和2

我們現在有要求,如果沒有「完美匹配「,這意味着只有material_id可以連接,並且對於b表中的location_id的連接,沒有material_id和location_id的正確組合(例如,material_id = 100和location_id = 1),連接應該爲」default 「或」後退「到location_id的其他可能值,例如material_id = 001和location_id = 2,反之亦然。這應該只適用於location_id。

我們已經查看過所有可能的答案也與CASE等,但沒有佔上風。像

... 
ON a.material_id=b.material_id AND a.location_id= 
CASE WHEN a.location_id = b.location_id THEN b.location_id ELSE ...; 

一個設置中,我們嘗試了還是沒搞清楚到底是如何在蜂巢查詢語言做。

謝謝你的幫助!也許有人有一個聰明的想法。

下面是一些示例數據:

Table a 
| material_id | location_id | other_column_a | 
| 100   | 1   | 45   | 
| 101   | 1   | 45   | 
| 103   | 1   | 45   | 
| 103   | 2   | 45   | 



Table b 
| material_id | location_id | other_column_b | 
| 100   | 1   | 66   | 
| 102   | 1   | 76   | 
| 103   | 2   | 88   | 


Left - Join Table 
| material_id | location_id | other_column_a | other_column_b 
| 100   | 1   | 45   | 66 
| 101   | 1   | 45   | NULL (mat. not in b) 
| 103   | 1   | 45   | DEFAULT TO where location_id=2 (88) 
| 103   | 2   | 45   | 88 

PS:如上所述here存在等在子查詢ON不起作用。

+0

我想,您需要向我們展示一些示例數據。 – Andrew

+0

謝謝Andrew,爲了清晰起見,我添加了一些示例數據。 – alpcoder

回答

0

解決的辦法是左無a.location_id = b.location_id和數量都行加入優先順序。然後按row_number進行過濾。在下面的代碼的聯接將重複行第一,因爲所有的匹配material_id將被加入,然後row_number()函數將分配1至行,其中a.location_id = b.location_id和2至a.location_id <> b.location_id如果存在還其中a.location_id = b.location_id和1,如果不存在這樣的行的行。 b.location_id添加到在ROW_NUMBER()函數order by因此它將萬一「喜歡」具有較低b.location_id行沒有精確匹配。我希望你已經發現了這個想法。

select * from 
(
SELECT 
    a.*, 
    b.*, 
    row_number() over(partition by material_id 
        order by CASE WHEN a.location_id = b.location_id THEN 1 ELSE 2 END, b.location_id) as rn 
FROM a 
LEFT JOIN (some more complex select) b 
    ON a.material_id=b.material_id 
)s 
where rn=1 
; 
+0

您確定的方法確實有效,這就是爲什麼我標記它有幫助。但是,我們的要求現在已經改變了,不需要硬編碼的位置。我將發佈我們當前的解決方案。 – alpcoder

+0

您能否解釋一下在這段代碼中硬編碼的內容? Location_id值不是硬編碼的,可以是任何 – leftjoin

+0

從我的理解來看,THEN 1 ELSE 2是硬編碼的,這將如何與更多的位置一起工作?但是你的答案是我最初提問的答案,並且工作正常。非常感謝你! – alpcoder

0

也許這是有人在將來有所幫助:

我們也提出了不同的方法。

首先,我們創建另一個表從基於material_id在所有(!)位置上的表B計算平均值。其次,在連接表中,我們創建三列: c1 - material_id和location_id匹配的值(表a和表b的左連接的結果)。如果沒有完美匹配,此列爲空。

C2 - 「實際值」列在這裏我們使用一個case語句 - 從我們寫信的平均值(後備)表中的號碼爲這個material_id

C3(不分位置)表中的值以確定列1是否爲NULL(沒有材料和位置的完美匹配),則我們使用列2中的值(材料的所有其他位置的平均值)進行進一步計算。

+0

THEN 1 ELSE 2 - 這些不是位置ID。這只是ROW_NUMBER()中用於標記行的ORDER值。標有1的行將首先排序,標有2的行將排在第二位,然後篩選結束時將過濾rn = 1。沒有任何硬編碼的列值。 – leftjoin

+0

你是對的。 – alpcoder