Last active
August 29, 2015 14:20
-
-
Save daynebatten/ddc6e706302c7c5e04fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* target_data is the data set you want to suppress | |
| dimensions is a pipe-separated list of dimensions to suppress */ | |
| %macro constraints(target_data, dimensions); | |
| /* Count the number of dimensions we're working with */ | |
| %let num_dims = %eval(%sysfunc(count(&dimensions, |)) + 1); | |
| /* Build a macro variable array with the dimension names */ | |
| %do i = 1 %to &num_dims; | |
| %let dim&i = %sysfunc(scan(&dimensions, &i, |)); | |
| %end; | |
| /* We need constraints for every combination of dimensions you can build by leaving out one dimension at a time. | |
| This is pretty simple in a 2-dimensional dataset. */ | |
| proc sql; | |
| create table | |
| levels | |
| %do i = 1 %to &num_dims; | |
| /* If this is the first loop through, we don't need the "union all"... */ | |
| %if &i = 1 %then %do; | |
| as | |
| %end; | |
| %else %do; | |
| union all | |
| %end; | |
| select distinct | |
| /* Include every dimension but the one we're leaving out. That one will just get a placeholder. */ | |
| %do j = 1 %to &num_dims; | |
| %if &j = &i %then %do; | |
| 'dummy' as &&dim&j | |
| %end; | |
| %else %do; | |
| &&dim&j | |
| %end; | |
| /* Add a comma unless it's the last dimension in the list */ | |
| %if &j < &num_dims %then %do; | |
| , | |
| %end; | |
| %end; | |
| from | |
| &target_data | |
| %end; | |
| /* Semicolon for the end of our SQL statement */ | |
| ; | |
| quit; | |
| /* Assign numbers to our soon-to-be constraints */ | |
| data levels; | |
| set levels; | |
| con = _n_; | |
| run; | |
| /* Merge our raw data with our constraint categories to determine which constraints apply to which data points */ | |
| proc sql; | |
| create table | |
| joined | |
| as select | |
| t.*, | |
| con, | |
| case when | |
| %do i = 1 %to &num_dims; | |
| /* If it's not the first loop, we need an "or" */ | |
| %if &i > 1 %then %do; | |
| or | |
| %end; | |
| /* We'll want to evaluate on a match across any set of all dimensions but one */ | |
| /* Start by opening our paren to keep the logic right */ | |
| ( | |
| %do j = 1 %to &num_dims; | |
| /* Need an "and" unless this is the first loop */ | |
| %if &j > 1 %then %do; | |
| and | |
| %end; | |
| /* If this is the dimension we're leaving out, look for a placeholder */ | |
| /* Otherwise, look for a real match on the dimension */ | |
| %if &i = &j %then %do; | |
| l.&&dim&j = 'dummy' and t.&&dim&j ~= 'ALL' | |
| %end; | |
| %else %do; | |
| l.&&dim&j = t.&&dim&j | |
| %end; | |
| %end; | |
| /* Close our paren */ | |
| ) | |
| %end; | |
| then 1 else 0 end as included | |
| from | |
| &target_data as t | |
| left join | |
| levels as l | |
| on | |
| 1 = 1; | |
| quit; | |
| /* Sort so we can transpose */ | |
| proc sort data = joined; | |
| by | |
| %do i = 1 %to &num_dims; | |
| &&dim&i | |
| %end; | |
| ; | |
| run; | |
| /* And transpose! */ | |
| proc transpose data = joined out = constraints(drop = _NAME_) prefix = con; | |
| by | |
| %do i = 1 %to &num_dims; | |
| &&dim&i | |
| %end; | |
| ; | |
| id con; | |
| var included; | |
| run; | |
| %mend; | |
| %constraints(Testset,degree|county); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment