As featured in: Data Management Solutions Using SAS Hash Table Operations: A Business Intelligence Case Study , and built from this github repository.
Chapter 5 GenerateSchedule.sas
1 /* "Chapter 5 GenerateSchedule.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  retain Team_SK Team1_SK Team2_SK .; /* define hash data items */
8  format Date yymmdd10.;
9 
10  declare hash team1(dataset:"bizarro.teams(rename=(Team_SK=Team1_SK))",multidata:"y");
11  rc = team1.defineKey("League_SK");
12  rc = team1.defineData("League_SK","Team1_SK");
13  rc = team1.defineDone();
14 
15  declare hash team2(dataset:"bizarro.teams(rename=(Team_SK=Team2_SK))",multidata:"y");
16  rc = team2.defineKey("League_SK");
17  rc = team2.defineData("League_SK","Team2_SK");
18  rc = team2.defineDone();
19 
20  declare hash matchUps(multidata:"y");
21  rc = matchUps.defineKey("League_SK");
22  rc = matchUps.defineData("League_SK","Team1_SK","Team2_SK");
23  rc = matchUps.defineDone();
24 
25  declare hash used();
26  rc = used.defineKey("League_SK","Team_SK");
27  rc = used.defineData("League_SK","Team_SK");
28  rc = used.defineDone();
29 
30  declare hash schedule();
31  rc = schedule.defineKey("League_SK","Team1_SK","Team2_SK");
32  rc = schedule.defineData("League_SK","Team1_SK","Team2_SK","Date","Home");
33  rc = schedule.defineDone();
34 
35  do League_SK = 1 to 2; /* loop thru Leagues */
36  Team1_rc = team1.find();
37  do while(Team1_rc=0); /* loop thru Team1 Teams */
38  Team2_rc = team2.find();
39  do while(Team2_rc=0); /* loop thru Team2 Teams for each Team1 team */
40  if Team2_SK ne Team1_SK then
41  do;
42  addrc = matchUps.add();
43  end;
44  Team2_rc = team2.find_next();
45  end; /* loop thru Team2 Teams for each Team1 team */
46  Team1_rc = team1.find_next();
47  end; /* loop thru Team1 Teams */
48  end; /* loop thru Leagues */
49 
50  do League_SK = 1 to 2; /* loop thru Leagues */
51  Date = "&seasonStartDate"d - 3;
52  do Combo = 1 to &nWeeksSeason; /* create the matchup sets */
53  if mod(combo,2) = 1 then Date + 3;
54  else Date + 4;
55  games = 0;
56  matchUps_rc = matchUps.find();
57  do while(matchUps_rc = 0 and games lt &nTeamsPerLeague/2);
58  if used.check(key:League_SK,key:Team1_SK) ne 0
59  and used.check(key:League_SK,key:Team2_SK) ne 0
60  then
61  do; /* combinations not yet used */
62  Home = ceil(uniform(&seed4)*2);
63  if schedule.add() = 0 then
64  do; /* add to schedule */
65  games + 1;
66  rc = used.add(Key:League_SK,Key:Team1_SK,Data:League_SK,Data:Team1_SK);
67  rc = used.add(Key:League_SK,Key:Team2_SK,Data:League_SK,Data:Team1_SK);
68  end; /* add to schedule */
69  end; /* combinations not yet used */
70  matchUps_rc = matchUps.find_next();
71  end;
72  used.clear(); /* loop thru matchups */
73  end;/* loop thru Leagues */
74  end;
75  schedule.output(dataset:"Games");
76  stop;
77 run;
78 
79 proc sort data = games out = games;
80  by League_SK Date;
81 run;
82 
83 data bizarro.games;
84  if 0 then set template.games;
85  drop Team1_SK Team2_SK Home D;
86  format Time Timeampm8.;
87  set games;
88  League = League_SK; /* fix for rename issue found post-publication */
89  D = Date;
90  retain D;
91  array _homeaway team1_sk team2_sk;
92  Home_SK = _homeaway(Home);
93  Away_SK = _homeaway(3-Home);
94  do Date = D to D+2;
95  Year = Year(Date);
96  Month = Month(Date);
97  DayOfWeek = weekday(Date);
98  if DayOfWeek = 5 then Time = "16:00"t;
99  else if DayOfWeek = 1 then Time = "13:00"t;
100  else time = "19:00"t;
101  Game_SK = md5(catx(":",League_SK,Away_SK,Home_SK,Date,Time));
102  output;
103  end;
104  /* Reverse home/away for second half of the season */
105  D + 7*&nWeeksSeason/2;
106  Home_SK = _homeaway(3-Home);
107  Away_SK = _homeaway(Home);
108  do Date = D to D+2;
109  Year = Year(Date);
110  Month = Month(Date);
111  DayOfWeek = weekday(Date);
112  Game_SK = md5(catx(":",League_SK,Away_SK,Home_SK,Date,Time));
113  output;
114  end;
115 run;