<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic How to: loop through SAS tables in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533743#M146372</link>
    <description>&lt;P&gt;Perhaps you want to preform a similar operation on multiple tables. Macro-tizing repetitive code can help. I prefer to use a &lt;A href="http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#z3514scan.htm" target="_self"&gt;%scan&lt;/A&gt; loop to loop through SAS tables or variables. If you can make a list of tables to loop through and get the count of the tables, the %scan function will do the hard work for you! This is most useful when you have a large number of tables to process, or are lazy and don't want to copy and paste code many times. Here are 3 examples going from brute-force to most efficient. The %scan function is in the 3rd example.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Examples for getting record counts with proc sql for 3 tables:&lt;/P&gt;&lt;P&gt;1. Hard-coded:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint;
	select count(*) into: count
	from sashelp.cars;
quit;
%put record count for cars = %sysfunc(strip(&amp;amp;count));
proc sql noprint;
	select count(*) into: count
	from sashelp.class;
quit;
%put record count for class = %sysfunc(strip(&amp;amp;count));
proc sql noprint;
	select count(*) into: count
	from sashelp.baseball;
quit;
%put record count for baseball = %sysfunc(strip(&amp;amp;count));&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Log shows counts from %put statements:&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for cars = 428&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for class = 19&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for baseball = 322&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. Single macro calls:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro get_record_count(table);
	proc sql noprint;
		select count(*) into: count
		from sashelp.&amp;amp;table;
	quit;
	%put record count for &amp;amp;table = %sysfunc(strip(&amp;amp;count));
%mend;
%get_record_count(table=cars)
%get_record_count(table=class)
%get_record_count(table=baseball)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Same log messages as option #1.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;3. Using the %scan loop. The %scan function will use the spaces between words as the default delimiter and return the same results:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let tables_to_process=cars class baseball;

%macro loopCall_record_count_macro(tables_to_process);
	
	%let to_loop_count = %sysfunc(countw(&amp;amp;tables_to_process));
	%put &amp;amp;to_loop_count;
	%put will process &amp;amp;to_loop_count tables &amp;amp;tables_to_process;

	%do i = 1 %to &amp;amp;to_loop_count;
		%let table = %scan(&amp;amp;tables_to_process,&amp;amp;i);
		proc sql noprint;
			select count(*) into: count
			from sashelp.&amp;amp;table;
		quit;
		%put record count for &amp;amp;table = %sysfunc(strip(&amp;amp;count));
	%end;
	
%mend;
%loopCall_record_count_macro(&amp;amp;tables_to_process)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Order of operations:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. List of tables to process defined in &amp;amp;tables_to_process with spaces between tables to loop over.&lt;/P&gt;&lt;P&gt;2. Macro is compiled then called&lt;/P&gt;&lt;P&gt;3. &amp;amp;to_loop_count is set to 3&lt;/P&gt;&lt;P&gt;4. %scan pulls out the 1st value (i=1 here), and assigns the value to &amp;amp;table, which is cars&lt;/P&gt;&lt;P&gt;5. proc sql runs against sashelp.cars&lt;/P&gt;&lt;P&gt;6.&amp;nbsp;%scan pulls out the 2nd value (i=2),&amp;nbsp;and assigns the value to &amp;amp;table, which is class, then proc sql runs again&lt;/P&gt;&lt;P&gt;7.&amp;nbsp;%scan pulls out the 3rd value (i=3), and assigns the value to &amp;amp;table, which is baseball, then proc sql runs again&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The log is the same for all 3 methods, wow!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To be even more efficient you could take the following steps, or add your own ideas!&lt;/P&gt;&lt;P&gt;1. Build the&amp;amp;tables_to_process using proc sql's "select into"&lt;/P&gt;&lt;P&gt;2. Use&amp;nbsp;%sysfunc(attrn(&amp;amp;dsid, nobs), proc contents with an 'out=' option , or sashelp or&amp;nbsp; proc sql's dictionaries tables to get the number of records in a dataset.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Thu, 07 Feb 2019 21:07:11 GMT</pubDate>
    <dc:creator>noling</dc:creator>
    <dc:date>2019-02-07T21:07:11Z</dc:date>
    <item>
      <title>How to: loop through SAS tables</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533743#M146372</link>
      <description>&lt;P&gt;Perhaps you want to preform a similar operation on multiple tables. Macro-tizing repetitive code can help. I prefer to use a &lt;A href="http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#z3514scan.htm" target="_self"&gt;%scan&lt;/A&gt; loop to loop through SAS tables or variables. If you can make a list of tables to loop through and get the count of the tables, the %scan function will do the hard work for you! This is most useful when you have a large number of tables to process, or are lazy and don't want to copy and paste code many times. Here are 3 examples going from brute-force to most efficient. The %scan function is in the 3rd example.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Examples for getting record counts with proc sql for 3 tables:&lt;/P&gt;&lt;P&gt;1. Hard-coded:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint;
	select count(*) into: count
	from sashelp.cars;
quit;
%put record count for cars = %sysfunc(strip(&amp;amp;count));
proc sql noprint;
	select count(*) into: count
	from sashelp.class;
quit;
%put record count for class = %sysfunc(strip(&amp;amp;count));
proc sql noprint;
	select count(*) into: count
	from sashelp.baseball;
quit;
%put record count for baseball = %sysfunc(strip(&amp;amp;count));&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Log shows counts from %put statements:&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for cars = 428&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for class = 19&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT size="1 2 3 4 5 6 7"&gt;record count for baseball = 322&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. Single macro calls:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro get_record_count(table);
	proc sql noprint;
		select count(*) into: count
		from sashelp.&amp;amp;table;
	quit;
	%put record count for &amp;amp;table = %sysfunc(strip(&amp;amp;count));
%mend;
%get_record_count(table=cars)
%get_record_count(table=class)
%get_record_count(table=baseball)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Same log messages as option #1.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;3. Using the %scan loop. The %scan function will use the spaces between words as the default delimiter and return the same results:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let tables_to_process=cars class baseball;

%macro loopCall_record_count_macro(tables_to_process);
	
	%let to_loop_count = %sysfunc(countw(&amp;amp;tables_to_process));
	%put &amp;amp;to_loop_count;
	%put will process &amp;amp;to_loop_count tables &amp;amp;tables_to_process;

	%do i = 1 %to &amp;amp;to_loop_count;
		%let table = %scan(&amp;amp;tables_to_process,&amp;amp;i);
		proc sql noprint;
			select count(*) into: count
			from sashelp.&amp;amp;table;
		quit;
		%put record count for &amp;amp;table = %sysfunc(strip(&amp;amp;count));
	%end;
	
%mend;
%loopCall_record_count_macro(&amp;amp;tables_to_process)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Order of operations:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. List of tables to process defined in &amp;amp;tables_to_process with spaces between tables to loop over.&lt;/P&gt;&lt;P&gt;2. Macro is compiled then called&lt;/P&gt;&lt;P&gt;3. &amp;amp;to_loop_count is set to 3&lt;/P&gt;&lt;P&gt;4. %scan pulls out the 1st value (i=1 here), and assigns the value to &amp;amp;table, which is cars&lt;/P&gt;&lt;P&gt;5. proc sql runs against sashelp.cars&lt;/P&gt;&lt;P&gt;6.&amp;nbsp;%scan pulls out the 2nd value (i=2),&amp;nbsp;and assigns the value to &amp;amp;table, which is class, then proc sql runs again&lt;/P&gt;&lt;P&gt;7.&amp;nbsp;%scan pulls out the 3rd value (i=3), and assigns the value to &amp;amp;table, which is baseball, then proc sql runs again&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The log is the same for all 3 methods, wow!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To be even more efficient you could take the following steps, or add your own ideas!&lt;/P&gt;&lt;P&gt;1. Build the&amp;amp;tables_to_process using proc sql's "select into"&lt;/P&gt;&lt;P&gt;2. Use&amp;nbsp;%sysfunc(attrn(&amp;amp;dsid, nobs), proc contents with an 'out=' option , or sashelp or&amp;nbsp; proc sql's dictionaries tables to get the number of records in a dataset.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 07 Feb 2019 21:07:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533743#M146372</guid>
      <dc:creator>noling</dc:creator>
      <dc:date>2019-02-07T21:07:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to: loop through SAS tables</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533805#M146405</link>
      <description>&lt;P&gt;Another approach:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint;
   select catx(".",libname,memname) 
   into :tables 
   separated by " "
   from dictionary.tables
   where libname="SASHELP" 
     and memtype="DATA"
   ;
quit;

%put &amp;amp;=tables;

%macro code;
   %put TABLE: %sysfunc(putc(&amp;amp;word,$20.)) %sysfunc(putn(%nobs(&amp;amp;word),comma15.));
%mend;
%loop(&amp;amp;tables)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;You could get NOBS directly from the dictionary table, this is just for illustration.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For example, you could change the %code macro to proc print data=&amp;amp;word (obs=10);run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The idea is to abstract the macro looping into its own macro, with the child macro %code written at "run time" and called for every token in the list passed to %loop.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I use this &lt;STRONG&gt;all the time&lt;/STRONG&gt;...&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;One more example:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* this is often faster than dictionary.columns, esp. if RBDMS libraries are allocated ;
proc contents data=sashelp.cars (keep=_numeric_) out=contents noprint;
run;
proc sql noprint;
   select name into :vars separated by " " from contents order by varnum;
   drop table contents;
quit;

%macro code;
   &amp;amp;word=_&amp;amp;word
%mend;
%macro convert_to_char;
   &amp;amp;word=put(_&amp;amp;word,best32.-l);
%mend;

data test;
   set sashelp.cars (obs=10 rename=(%loop(&amp;amp;vars)));
   %loop(&amp;amp;vars,mname=convert_to_char)
   drop _:;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&lt;A href="https://github.com/scottbass/SAS/blob/master/Macro/loop.sas" target="_blank"&gt;https://github.com/scottbass/SAS/blob/master/Macro/loop.sas&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="https://github.com/scottbass/SAS/blob/master/Macro/nobs.sas" target="_blank"&gt;https://github.com/scottbass/SAS/blob/master/Macro/nobs.sas&lt;/A&gt;&lt;/P&gt;&lt;P&gt;&lt;A href="https://github.com/scottbass/SAS/blob/master/Macro/loop_control.sas&amp;nbsp;" target="_blank"&gt;https://github.com/scottbass/SAS/blob/master/Macro/loop_control.sas&amp;nbsp;&lt;/A&gt; (if your metadata won't fit into a macro variable - rare)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;HTH...&lt;/P&gt;</description>
      <pubDate>Fri, 08 Feb 2019 02:09:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533805#M146405</guid>
      <dc:creator>ScottBass</dc:creator>
      <dc:date>2019-02-08T02:09:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to: loop through SAS tables</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533810#M146407</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/115150"&gt;@noling&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And if you've got SAS DI Studio then you can implement something like this using the Loop transformation which then also allows you to run such processes in parallel and/or SAS Grid enabled without any additional coding required.&lt;/P&gt;</description>
      <pubDate>Fri, 08 Feb 2019 02:53:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533810#M146407</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2019-02-08T02:53:29Z</dc:date>
    </item>
    <item>
      <title>Re: How to: loop through SAS tables</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533906#M146436</link>
      <description>I like the idea of putting the %loop into it's own macro. I often write out the loop 1x per rename/drop/convert, but it's much easier to read your way!</description>
      <pubDate>Fri, 08 Feb 2019 13:29:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-loop-through-SAS-tables/m-p/533906#M146436</guid>
      <dc:creator>noling</dc:creator>
      <dc:date>2019-02-08T13:29:06Z</dc:date>
    </item>
  </channel>
</rss>

