2017-05-25 73 views
3

我通常在使用PROC SQL的時候加入了一個表,它也有一個日期條件(即target_date落在start_date和end_date之間)。PROC SQL上的散列連接等價物

我已經能夠成功地把這種以哈希考慮在內時,加入加盟:

data hash_join; 
if _n_ = 1 then do; 
    declare hash add1(dataset:'table_2',multidata: 'Y'); 
    add1.defineKey('key_1'); 
    add1.defineData('start_date','end_date','value_1'); 
    add1.defineDone(); 
end; 

format 
    start_date date9. 
    end_date date9. 
    value_1 10.5 
; 

set table_1 (keep=key_1 target_date); 

if add1.find() = 0 then do until (add1.find_next()); 
    if start_date le target_date le end_date then output; 
end; 
run; 

這是同樣的事情:

proc sql; 
create table sql_join as select 
b.start_date, 
b.end_date, 
b.value_1, 
a.key_1, 
a.target_date 
from table_1 a 
inner join table_2 b 
on a.key_1 = b.key_1 and 
a.target_date between b.start_date and b.end_date 
;quit; 

我無法搞清楚儘管相當於左連接。舉例來說,如果事情不加入,我想輸出,我認爲這是簡單的:

if add1.find() ne 0 then output; 

如果它的連接和日期間,這看起來非常簡單,以及:

if add1.find() = 0 then do until (add1.find_next()); 
    if start_date le target_date le end_date then output; 
end; 

但是,如何從可能加入的table_1中獲取記錄的其餘記錄,但start_date和end_date之間沒有target_date?例如,假設table_2是銷售的開始日期和結束日期,並且該銷售直到2月1日纔開始,key_1 ='衣服'。如果我的table_1在1月1日有'Clothes'和銷售,它將加入密鑰,但我想輸出空白值。任何想法如何做到這一點?

任何幫助將不勝感激!

回答

3

你只需要跟蹤你是否找到了匹配。由於你沒有使用散列查找來追蹤事物之間的'中間',所以你不能使用它,所以你只需要自己做。

看到這個例子。在這裏,我將SASHELP.CLASS修改爲您的輸入表,然後添加一些邏輯來查看是否找到任何內容。

data table_1; 
    set sashelp.class; 
    rename age=target_date name=key_1; 
    drop height weight; 
run; 

data table_2; 
    set sashelp.class; 
    do _i = 1 to mod(_n_,3); 
    start_date = age-3+_i; 
    end_date = age+1-_i; 
    if start_date le end_date then output; 
    end; 
    rename name=key_1 height=value_1; 
    keep height weight start_date age end_date name; 
run; 

data hash_join; 
if _n_ = 1 then do; 
    declare hash add1(dataset:'table_2',multidata: 'Y'); 
    add1.defineKey('key_1'); 
    add1.defineData('start_date','end_date','value_1'); 
    add1.defineDone(); 
end; 

format 
    start_date date9. 
    end_date date9. 
    value_1 10.5 
; 

set table_1 (keep=key_1 target_date); 

if add1.find() = 0 then do until (add1.find_next()); 
    if start_date le target_date le end_date then do; 
     found=1; 
     output; 
    end; 
end; 
call missing(of value_1); *full list of values to clear - all of hash data elements; 
if not (found) then output; 
run; 
+0

因爲我的孩子會說,「JINX」 – DomPazz

+1

大聲笑。是的,我們分別做了非常相似的代碼......並且fwiw,將你的代碼粘貼到我的代碼上,但是使用我的樣本數據能正常工作。 – Joe

+0

謝謝你們兩位! – Derek

3

我想你只需要跟蹤,如果事情有鑰匙,但不是在範圍:

if add1.find() ^=0 then output; 
else do; 
    found = 0; 
    do until (add1.find_next()); 
     if start_date le target_date le end_date then do; 
      output; 
      found=1; 
     end; 
    end; 
    if ^found then output; 
end; 

沒有任何數據與測試,所以這只是我的編碼SO。讓我知道如果它不起作用。