BookmarkSubscribeRSS Feed
learsaas
Quartz | Level 8
/*method 1:SQL*/
%macro getResult;
	%local i j NOBS1 NOBS2;
	proc sql noprint;
		create table test_left as
			select * 
			from test 
			;
		create table test_result as
			select *,'' as UID length=20
			from test_left
			where 1=2
			;
	quit;

	%let i=1;
	%do %until(%left(&NOBS1) eq 0);
		%let NOBS1=0;
		proc sql noprint;
			select count(*) into :NOBS1 from test_left; 
		quit;

		%if %left(&NOBS1) gt 0 %then %do;
			%let j=1;
			%do %until(%left(&NOBS2) eq 0);
				%if &j eq 1 %then %do;
					proc sql noprint;
						create table test_id as
							select distinct cust 
							from test_left(firstobs=1 obs=1)
							;
					quit;
				%end;
				%else %do;
					proc sql noprint;
						create table test_id as
							select distinct cust 
							from test_left
							where dev in (select distinct dev from test_temp)
							;
					quit;
				%end;
					proc sql noprint;
						create table test_temp as
							select * 
							from test_left 
							where cust in (select distinct cust from test_id)
							;
						create table test_left as
							select * 
							from test_left 
							where cust not in (select distinct cust from test_id)
							;
					quit;			

			
				%let NOBS2=0;
				proc sql noprint;
					select count(*) into :NOBS2 from test_temp; 
				quit;

				%if %left(&NOBS2) gt 0 %then %do;	
					proc sql noprint;
						insert into test_result
							select *,cats('UID',"%left(&i)") as UID length=20
							from test_temp
							;
					quit;
				%end;
				%let j=%eval(&j+1);
			%end;
		%end;
		%let i=%eval(&i+1);
	%end;
	proc sql noprint;
		drop table test_left;
		drop table test_temp;
		drop table test_id;
	quit;
%mend;
%getResult;

/*method 2*/
%macro getResult;
	%local i j NOBS1 NOBS2;
	data test_left;
		set test;
	run;
	data test_result;
		set test_left;
		attrib UID length=$20;
		stop;
	run;
	%let i=1;
	%do %until(%left(&NOBS1 eq 0));
		%let NOBS1=0;
		proc sql noprint;
			select count(*) into :NOBS1 from test_left; 
		quit;
		%if %left(&NOBS1) gt 0 %then %do;
			%let j=1;
			%do %until(%left(&NOBS2 eq 0));
				%if &j eq 1 %then %do;
					data test_id;
						set test_left(firstobs=1 obs=1);			
					run;
				%end;
				%else %do;
					proc sql noprint;
						create table test_id as
							select distinct cust 
							from test_left
							where dev in (select distinct dev from test_temp)
							;
					quit;
				%end;
				data  test_left test_temp;
					set test_left;
					Flag=0;
					do i=1 to ncount;
						set test_id(keep=cust rename=(cust=cust_id)) nobs=ncount point=i;
						if cust_id=cust then do;Flag=1;leave;end;
					end;
					if flag=1 then output test_temp;else output test_left;	
					drop flag cust_id;
				run;				
				%let NOBS2=0;
				proc sql noprint;
					select count(*) into :NOBS2 from test_temp; 
				quit;
				%if %left(&NOBS2) gt 0 %then %do;	
					data  temp;
						set test_temp;
						UID='UID'||"%left(&i)";
					run;
					proc append base=test_result data=temp force;
					run;
				%end;	
				%let j=%eval(&j+1);
			%end;
		%end;
		%let i=%eval(&i+1);
	%end;
	proc delete data=test_left;run;
	proc delete data=test_temp;run;
	proc delete data=test_id;run;
	proc delete data=temp;run;
%mend;
%getResult;
novinosrin
Tourmaline | Level 20

Hi @kilo_foxtrot  This is close to applying brute force. Try and let me know.

 

data have;
length cust dev $5;
input cust $ dev $;
datalines;
a 1
a 2
a 7
b 2
b 3
c 3
d 4
e 5
h 2
x 4
x 5
y 7
y 5
;
run;

dm log 'clear';
/*Intial look up*/
data _null_;
if _n_=1 then do;
length uid __dev __cust $5;
if 0 then set have(rename=(dev=_dev cust=_cust));
  declare hash H (multidata:'yes') ;
   h.definekey  ("__cust") ;
   h.definedata ("__cust","__dev","uid") ;
   h.definedone () ;
   declare hash H1 (dataset:'have(rename=(dev=_dev cust=_cust))', multidata:'yes') ;
   h1.definekey  ("_dev") ;
   h1.definedata ("_cust","_dev") ;
   h1.definedone () ;
   declare hiter hi('h');
   declare hiter hh('h1');
   call missing(__cust,__dev);
end;
array t(999) $5;
n=0;
do until(last.cust);
	set have end=l;
	by cust;
	if first.cust then 
		do;
			if h.find(key:cust) = 0 then f1=1;
			do while(hi.next()=0);
			if dev=__dev	then do; f2=1;leave;end;
			end;
			if sum(f1, f2)=. then do;c+1;uid =cats( 'UID', put(c,8. -l)); end;
		end;
	 do rc1=h1.find(key:dev) by 0 while(rc1=0);
		rc=h.add(key:_cust,data:_cust,data: _dev,data:uid);
		if _cust ne cust then do;
		n+1;
		t(n)=_cust;
		end;
		rc1=h1.find_next();
	end;
end;
do i=1 to dim(t);
	if not missing(t(i)) then 
	do while(hh.next()=0);
	if t(i)=_cust then rc=h.add(key:_cust,data:_cust,data: _dev,data:uid);
		do rc1=h1.find(key:_dev) by 0 while(rc1=0);
		rc=h.add(key:_cust,data:_cust,data: _dev,data:uid);
		rc1=h1.find_next();
		end;
	end;
end;
if l then h.output(dataset:'w');
run;

/*Final Want	*/
proc sort data=w out=want nodupkey;
by uid __cust __dev;
run;

There is still a glitch. Ignore this post .Another garbage.hmm let me try again

novinosrin
Tourmaline | Level 20

HI @kilo_foxtrot  I spent sometime talking to my mate and researching online. It seems networking problems often tend to have routes(paths) that can be infinite  as in our example, the more I try the link keeps going, on and on and on. Sure this can only go so far because the dataset isn't infinite but i think grouping one that is vast and expanded with duplicates needs a different approach.

 

Anyways, Can you provide me some logical/mathematical insight without referring to technology/functionality to guage how the loop stops from your experience/knowledge. 

 

 

Ignore all. Understood all but my brain didn't function well. My bad

novinosrin
Tourmaline | Level 20

Hi @kilo_foxtrot  Dec,17,2018 attempt

 

data have;
length cust dev $5;
input cust $ dev $;
datalines;
a 1
a 2
a 51
b 2
b 3
c 3
d 4
e 5
h 2
x 4
x 5
y 7
y 5
z 8
k 6
l 9
l 3
j 51
j 9
j 1
m 11
n 13
;
run;

proc sort data=have;
by cust dev;
run;
dm log 'clear';

data _null_;
if _n_=1 then do;
  if 0 then set have(rename=(dev=_dev cust=_cust));
  length __dev UID __cust $5;
	/*H initial full load*/
  dcl hash H (dataset:'have(rename=(dev=_dev cust=_cust))',multidata:'y') ;
   h.definekey  ("_dev") ;
   h.definedata ("_cust", "_dev") ;
   h.definedone () ;
   dcl hiter hh('h');
   	/*H1 Look up and load part by part load proceeding to our need*/
   dcl hash H1 (multidata:'y',ordered:'y') ;
   h1.definekey  ("__cust") ;
   h1.definedata ("__cust", "__dev","UID") ;
   h1.definedone () ;
   dcl hiter hh1('h1');
   call missing(__dev,__cust);
end;
array t(999) $5;
array j(999) $5;
do until(last.cust);
	set have end=l;
	by cust;
	if first.cust then 
	do;
		if  h1.find(key:cust)= 0 then f=1;
		if not f then do; c+1; uid= cats( 'UID', put(c,8. -l));end;
	end;
	if not f then 
	do;
		/*Look from dev to cust and collect cust residuals in array*/
			do rc1=h.find(key:dev) by 0 while(rc1=0);
				rc=h1.add(key:_cust,data:_cust,data:_dev,data:uid);
		/*collect cust residuals in array that's not part of cust but part of device*/
				if _cust ne cust then do;n+1;t(n)=_cust;end;
				rc1=h.find_next();
			end;
	end;
end;
n=0;
if not f then 
do;
	/*Residual look up-start with cust and iterate with dev*cust recursively until all check complete*/
	do until(sum(cmiss(of t(*)),cmiss(of j(*)))=dim(t)*2);
		do i=1 to dim(t);
			if not missing(t(i)) then 
	/*iterate the full load h using hh*/
				do while(hh.next()=0);
					if t(i)=_cust then
					do;
		/*Check if residual cust's* dev is not in part load hash,if not then fetch*/
						k=.;
						do while(hh1.next()=0);
						if __dev = _dev then do; k=1;leave;end;
						end;
						if not  k then do;n1+1;j(n1)=_dev;end;
						rc=h1.add(key:_cust,data:t(i),data:_dev,data:uid);
					end;	
				end;
		end;
		call missing(of t(*));n1=0;
		do i=1 to dim(j);
			if not missing(j(i)) then 
				do rc1=h.find(key:j(i)) by 0 while(rc1=0);
			/*Check if residual dev's *cust is not in part load hash,if not then fetch*/
					if h1.check(key:_cust) ne 0 then do;n+1;t(n)=_cust;end;
					rc=h1.add(key:_cust,data:_cust,data:_dev,data:uid);
					rc1=h.find_next();
				end;
		end;
		call missing(of j(*));n=0;
	end;
end;
if l then h1.output(dataset:'want');
run;

proc sort data=want out=final_want nodupkey ;
by uid __cust __dev ;
run;


SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 18 replies
  • 3067 views
  • 0 likes
  • 4 in conversation