As featured in: Data Management Solutions Using SAS Hash Table Operations: A Business Intelligence Case Study , and built from this github repository.
Chapter 7 SCD 6.sas
1 /* "Chapter 7 SCD 6.sas" from the SAS Press book
2  Data Management Solutions Using SAS Hash Table Operations:
3  A Business Intelligence Case Study
4 */
5 
6 data _null_;
7  if 0 then set template.Players_SCD6;
8  if _n_ = 1 then
9  do; /* define the hash table */
10  dcl hash scd(dataset:
11  ifc(exist("bizarro.Players_SCD6")
12  ,"bizarro.Players_SCD6"
13  ,"template.Players_SCD6"
14  )
15  ,ordered:"A",multidata:"Y");
16  scd.defineKey("Player_ID");
17  scd.defineData("Player_ID","Active","SubKey"
18  ,"Team_SK","First_Name","Last_Name"
19  ,"Position_Code","Bats","Throws"
20  ,"Start_Date","End_Date");
21  scd.defineDone();
22  end; /* define the hash table */
23  set bizarro.atbats
24  (rename = (Batter_ID = Player_ID
25  Team_SK = _Team_SK
26  First_Name = _First_Name
27  Last_Name = _Last_Name
28  Position_Code = _Position_Code
29  Bats = _Bats
30  Throws = _Throws)
31  ) end=lr;
32  if scd.check(Key:Player_ID) ne 0 then
33  do; /* player is new */
34  scd.add(key: Player_ID
35  ,data: Player_ID
36  ,data: 1
37  ,data: 1
38  ,data: _Team_SK
39  ,data: _First_Name
40  ,data: _Last_Name
41  ,data: _Position_Code
42  ,data: _Bats
43  ,data: _Throws
44  ,data: Date
45  ,data: &SCD_End_Date
46  );
47  end; /* player is new */
48  else
49  do; /* check to see if there are changes */
50 
51  RC = scd.find();
52  do while(RC = 0);
53  if (Start_Date le Date le End_Date) then leave;
54  RC = scd.find_next();
55  end;
56  if RC ne 0 then
57  call missing(Team_SK,First_Name,Last_Name
58  ,Position_Code,Bats,Throws);
59 
60  if catx(":", Team_SK, First_Name, Last_Name
61  , Position_Code, Bats, Throws) ne
62  catx(":",_Team_SK,_First_Name,_Last_Name
63  ,_Position_Code,_Bats,_Throws) then
64  do; /* date out prior record and add new one */;
65 
66  if RC = 0 then /* date out active record */
67  scd.replaceDup(data: Player_ID
68  ,data: 0
69  ,data: SubKey
70  ,data: Team_SK
71  ,data: First_Name
72  ,data: Last_Name
73  ,data: Position_Code
74  ,data: Bats
75  ,data: Throws
76  ,data: Start_Date
77  ,data: Date - 1
78  );
79 
80  /* add row with the next autonumber value */
81  _SubKey = 0;
82  RC = scd.find();
83  do while(RC = 0);
84  RC = scd.find_next();
85  _SubKey = max(_SubKey,SubKey);
86  end;
87  scd.add(key: Player_ID
88  ,data: Player_ID
89  ,data: 1
90  ,data: _SubKey + 1
91  ,data: _Team_SK
92  ,data: _First_Name
93  ,data: _Last_Name
94  ,data: _Position_Code
95  ,data: _Bats
96  ,data: _Throws
97  ,data: Date
98  ,data: &SCD_End_Date
99  );
100  end; /* date out prior record and add new one */;
101  end; /* check to see if there are changes */
102  if lr;
103  scd.output(dataset:"Bizarro.Players_SCD6"
104  || "(index=(SCD6=(Player_ID Active SubKey)))");
105 run;
106 
107 data tableLookup;
108  /* Sample Lookup */
109  retain Player_ID;
110  if 0 then set bizarro.Players_SCD6(drop=Subkey);
111  if _n_ = 1 then
112  do; /* define the hash table */
113  dcl hash scd(dataset:"bizarro.Players_SCD6"
114  ,multidata:"Y",ordered:"D");
115  scd.defineKey("Player_ID","Active");
116  scd.defineData("Team_SK","Player_ID","Active"
117  ,"First_Name","Last_Name"
118  ,"Position_Code","Bats","Throws"
119  ,"Start_Date","End_Date");
120  scd.defineDone();
121  end; /* define the hash table */
122  infile datalines;
123  attrib Date format = yymmdd10. informat = yymmdd10.;
124  input Player_ID Date;
125  RC = scd.find(Key:Player_ID,Key:1);
126  if RC = 0 and (Start_Date le Date le End_Date)
127  then;
128  else
129  do; /* search the inactive rows */
130  RC = scd.find(Key:Player_ID,Key:0);
131  do while(RC = 0);
132  if (Start_Date le Date le End_Date) then leave;
133  RC = scd.find_next();
134  end;
135  end; /* search the inactive rows */
136  if RC ne 0 then
137  call missing(Team_SK,Active,First_Name
138  ,Last_Name,Position_Code,Bats
139  ,Throws,Start_Date,End_Date);
140 datalines;
141 10103 2017/10/15
142 10103 2017/03/23
143 99999 2017/03/15
144 10782 2017/03/22
145 10782 2017/03/21
146 run;