As featured in: Data Management Solutions Using SAS Hash Table Operations: A Business Intelligence Case Study , and built from this github repository.
Chapter 11 Combined Techniques Join.sas
1 /* "Chapter 11 Combined Techniques Join.sas" from the SAS Press book
2  Data Management Solutions Using SAS Hash Table Operations:
3  A Business Intelligence Case Study
4 */
5 
6 %let comp_keys = Game_SK Inning Top_Bot AB_Number ;
7 %let sort_keys = Game_SK ;
8 %let data_vars = Batter_ID Position_code Is_A_Hit Result ;
9 %let tail_keys = %sysfunc (tranwrd (&comp_keys, &sort_keys, %str())) ;
10 %let last_key = %sysfunc (scan (&sort_keys, -1)) ;
11 %let tail_list = %sysfunc (tranwrd (&tail_keys, %str( ), %str(,))) ;
12 %let data_list = %sysfunc (tranwrd (&data_vars, %str( ), %str(,))) ;
13 
14 data Join_Runs_AtBats_combine (drop = _: Runs) ;
15  if _n_ = 1 then do ;
16  dcl hash h (multidata:"Y", ordered:"A") ;
17  h.defineKey ("_MD5") ;
18  h.defineData ("RID") ;
19  h.defineDone() ;
20  end ;
21  do until (last.&last_key) ;
22  set dw.AtBats (in=A keep=&comp_keys Runs)
23  dw.Runs (in=R keep=&comp_keys Runner_ID) ;
24  by &sort_keys ;
25  if A = 1 then do ;
26  _RID + 1 ;
27  if not Runs then continue ;
28  end ;
29  length _concat $ 37 _MD5 $ 16 ;
30  _concat = catx (":", &tail_list) ;
31  _MD5 = md5 (_concat) ;
32  if A = 1 then h.add(key:_MD5, data:_RID) ;
33  if R = 0 then continue ;
34  do while (h.do_over() = 0) ;
35  _count = sum (_count, 1) ;
36  set dw.AtBats (keep=&data_vars) point=RID ;
37  output ;
38  end ;
39  if not _count then output ;
40  call missing (&data_list, _count) ;
41  end ;
42  h.clear() ;
43 run ;