forked from edwinhu/sas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMERGE_ASOF.sas
111 lines (107 loc) · 2.89 KB
/
MERGE_ASOF.sas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
Author: Edwin Hu
Date: 2019-02-02
# MERGE_ASOF #
## Summary ##
Does an as-of or "window" merge
## Variables ##
- a: dataset a
- b: dataset b
- merged: output merged dataset
- idvar: firm identifier (permno)
- datevar: date variable to use (date)
- num_vars: numeric variables from b to merge in
- char_vars: character variables from b to merge in
## Usage ##
```
%INCLUDE "~/git/sas/MERGE_ASOF.sas";
%MERGE_ASOF(a=,b=,
merged=,
num_vars=);
```
*/
%MACRO MERGE_ASOF(a=,b=,
lib=USER,
merged=,
idvar=permno,
datevar=date,
num_vars=,
char_vars=,
sort_statement=&idvar. &datevar.);
%local nlen clen;
data _ncols;
set _null_;
retain &num_vars. .;
run;
%if %sysevalf(%superq(char_vars)^=,boolean) %then %do;
data _ccols;
set _null_;
retain &char_vars. '';
run;
%end;
proc sql noprint;
select compress(a.name)||"_ "||compress(put(a.length,3.))||"."
into :nlen separated by ' '
from dictionary.columns a
inner join
dictionary.columns b
on upcase(a.name) = upcase(b.name)
where upcase(a.libname)=upcase("&lib.")
and upcase(a.memname)=upcase("&b.")
and upcase(b.libname)=upcase("&lib.")
and upcase(b.memname)="_NCOLS"
;
quit;
%if %sysevalf(%superq(char_vars)^=,boolean) %then %do;
proc sql NOPRINT;
select compress(a.name)||"_ $"||compress(put(a.length,3.))||"."
into :clen separated by ' '
from dictionary.columns a
inner join
dictionary.columns b
on upcase(a.name) = upcase(b.name)
where upcase(a.libname)=upcase("&lib.")
and upcase(a.memname)=upcase("&b.")
and upcase(b.libname)=upcase("&lib.")
and upcase(b.memname)="_CCOLS"
;
quit;
%end;
data &merged.;
length &nlen. &clen.;
retain
%local i next_name;
%do i=1 %to %sysfunc(countw(&num_vars.));
%let next_name = %scan(&num_vars., &i);
&next_name._ .
%end;
%if %sysevalf(%superq(char_vars)^=,boolean) %then %do;
%do i=1 %to %sysfunc(countw(&char_vars.));
%let next_name = %scan(&char_vars., &i);
&next_name._ ''
%end;%end;;
set &b.(in=b keep=&idvar. &datevar. &num_vars. &char_vars.)
&a.(in=a);
by &sort_statement.;
if first.&idvar. then do;
%do i=1 %to %sysfunc(countw(&num_vars.));
%let next_name = %scan(&num_vars., &i);
&next_name._=.;
%end;
%if %sysevalf(%superq(char_vars)^=,boolean) %then %do;
%do i=1 %to %sysfunc(countw(&char_vars.));
%let next_name = %scan(&char_vars., &i);
&next_name._='';
%end;
%end;
end;
%do i=1 %to %sysfunc(countw(&num_vars. &char_vars.));
%let next_name = %scan(&num_vars. &char_vars., &i);
if not missing(&next_name.) then &next_name._=&next_name.;
drop &next_name.;
rename &next_name._=&next_name.;
%end;
format &datevar. yymmdd10.;
if a then output;
run;
%MEND;