<?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 Re: Finding a value in all datasets in all variables - revisited in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572992#M161733</link>
    <description>&lt;P&gt;Well this looked kind of fun &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's my take on it.&amp;nbsp; Perhaps someone can suggest performance improvements but it has acceptable performance on SASHELP.&amp;nbsp; %code1 performs better but can miss hits if you're searching for multiple strings.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'll leave it to you to finish "macro-izing" it, such as wrapping it in a top level macro, case-insensitive search, etc.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Go here to download the macros:&amp;nbsp;&amp;nbsp;&lt;A href="https://github.com/scottbass/SAS/tree/master/Macro" target="_blank" rel="noopener"&gt;https://github.com/scottbass/SAS/tree/master/Macro&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* list of datasets ;
proc sql noprint;
   select catx('.',libname,memname) 
   into   :datasets separated by ' '
   from   dictionary.tables
   where  libname="SASHELP" 
     and  memtype='DATA'
   ;
quit;

%put &amp;amp;datasets;

* macro to process the datasets ;
%macro code1;
data temp;
   length _dataset_ $32 _variable_ $32 _value_ $200 _dsname_ $41;
   set &amp;amp;word indsname=dsname;
   array vars{*} _character_;
   do i=1 to dim(vars);
      if vars{i} in (%seplist(&amp;amp;value,indlm=^,nest=q)) then do;
         _dataset_=dsname;
         _variable_=vname(vars{i});
         _value_=vars{i};
         output;
         stop;
      end;
   end;
   keep _dataset_ _variable_ _value_;
run;
proc append 
   base=results1 
   data=temp (rename=(_dataset_=dataset _variable_=variable _value_=value))
;
run;
%mend;

* Alternative, slower but more complete ;
%macro code2;
data temp;
   length _dataset_ $32 _variable_ $32 _value_ $200 _dsname_ $41;
   set &amp;amp;word indsname=dsname;
   array vars{*} _character_;
   do i=1 to dim(vars);
      if vars{i} in (%seplist(&amp;amp;value,indlm=^,nest=q)) then do;
         _dataset_=dsname;
         _variable_=vname(vars{i});
         _value_=vars{i};
         output;
         * stop;
      end;
   end;
   keep _dataset_ _variable_ _value_;
run;
proc sort noduprecs;
   by _all_;
run;
proc append 
   base=results2 
   data=temp (rename=(_dataset_=dataset _variable_=variable _value_=value))
;
run;
%mend;

%kill(data=results1 results2);

%let value=Ketchikan^New York^Alice^IBM;

* testing ;
/*%loop(sashelp.zipcode,mname=code1)*/

* the whole shebang ;
* note this misses some hits in zipcode because the stop statement stops on the first hit ;
%loop(&amp;amp;datasets,mname=code1)

* alternative approach ;
%loop(&amp;amp;datasets,mname=code2)

&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Fri, 12 Jul 2019 05:02:43 GMT</pubDate>
    <dc:creator>ScottBass</dc:creator>
    <dc:date>2019-07-12T05:02:43Z</dc:date>
    <item>
      <title>Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572914#M161697</link>
      <description>&lt;P&gt;Here's my take on it.&amp;nbsp; Finds all tables with at least one char field with the selected value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro findvalue;

	%let value=vincent;

	proc sql noprint;

		SELECT distinct cats(libname,'.',memname),   'work.' || memname
		into :libmemname1-,:worklibmemname1-
		FROM dictionary.columns t1
		WHERE type = 'char'
			AND libname='ELTSSDE';

	%let memobs = &amp;amp;sqlobs;

	%do j=1 %to &amp;amp;memobs;

		SELECT name
			into :name1-
			FROM dictionary.columns t1
			WHERE type = 'char' 
				and cats(libname,'.',memname)="&amp;amp;&amp;amp;libmemname&amp;amp;j"
				AND libname='ELTSSDE';

		%let colobs = &amp;amp;sqlobs;

		%if &amp;amp;colobs=0 %then %return;

		create table &amp;amp;&amp;amp;worklibmemname&amp;amp;j as
			select * from &amp;amp;&amp;amp;libmemname&amp;amp;j

/*	%put &amp;amp;&amp;amp;worklibmemname&amp;amp;j &amp;amp;&amp;amp;libmemname&amp;amp;j;*/

		%do i=1 %to &amp;amp;colobs;

			%if &amp;amp;i=1 %then %let whereor = where ; %else %let whereor = or;

			&amp;amp;whereor upcase(&amp;amp;&amp;amp;name&amp;amp;i ) = upcase("&amp;amp;value")

/*			%put &amp;amp;whereor &amp;amp;&amp;amp;name&amp;amp;i;*/

		%end;

			;

		%if &amp;amp;sqlobs=0 %then drop table &amp;amp;&amp;amp;worklibmemname&amp;amp;j;
			;

	%end;

%mend findvalue;

%findvalue;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 11 Jul 2019 19:41:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572914#M161697</guid>
      <dc:creator>tomrvincent</dc:creator>
      <dc:date>2019-07-11T19:41:17Z</dc:date>
    </item>
    <item>
      <title>Re: Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572948#M161710</link>
      <description>&lt;P&gt;Restrict the variable selection to only those with a length as long or greater as the value you are searching for might help increase efficiency a bit.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="token statement"&gt;WHERE&lt;/SPAN&gt; type &lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt; &lt;SPAN class="token string"&gt;'char'&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp; and length ge length("&amp;amp;value")&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The actual value would be much better off as a Parameter to the macro.&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="token macrobound"&gt;%macro&lt;/SPAN&gt; findvalue (value);&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;sort of confused about a specific libname in the WHERE clause though.&lt;/P&gt;
&lt;P&gt;If a character variable is found in the WORk library then there isn't a need that I can see for &amp;nbsp; &lt;SPAN class="token string"&gt;'work.'&lt;/SPAN&gt; &lt;SPAN class="token operator"&gt;||&lt;/SPAN&gt; memname as the &lt;SPAN class="token function"&gt;cats&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;&lt;SPAN class="token statement"&gt;libname&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;,&lt;/SPAN&gt;&lt;SPAN class="token string"&gt;'.'&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;,&lt;/SPAN&gt;memname&lt;SPAN class="token punctuation"&gt;) should create "work.memname".&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 11 Jul 2019 21:15:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572948#M161710</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2019-07-11T21:15:10Z</dc:date>
    </item>
    <item>
      <title>Re: Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572989#M161731</link>
      <description>&lt;P&gt;Also you seem to use &lt;FONT face="courier new,courier"&gt;%return&lt;/FONT&gt; wrongly, which will affect the results by ending the macro prematurely.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This version would work as intended, be faster and be clearer imho:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro findvalue(lib=, value=, icase=1);

  %local memnb memno colnb colno;

  proc sql noprint;

    select distinct MEMNAME
    into :memname1-
    from DICTIONARY.COLUMNS 
    where LIBNAME eq "&amp;amp;lib" 
      and TYPE    eq 'char' 
      and LENGTH  ge length("&amp;amp;value");

    %let memnb = &amp;amp;sqlobs.;

    %do memno=1 %to &amp;amp;memnb.;

      select NAME into :varname1-
        from DICTIONARY.COLUMNS 
        where LIBNAME eq "&amp;amp;lib" 
          and MEMNAME eq "&amp;amp;&amp;amp;memname&amp;amp;memno"
          and TYPE    eq 'char' 
          and LENGTH  ge length("&amp;amp;value");

      %let colnb = &amp;amp;sqlobs.;

      %if &amp;amp;colnb. %then %do;
        create table WORK.ZZ&amp;amp;&amp;amp;memname&amp;amp;memno. as
          select * from &amp;amp;lib..&amp;amp;&amp;amp;memname&amp;amp;memno.
          %do colno=1 %to &amp;amp;colnb.;
            %if &amp;amp;colno=1 %then where ; %else or;
            %if &amp;amp;icase. %then 
              upcase(&amp;amp;&amp;amp;varname&amp;amp;colno. ) = upcase("&amp;amp;value");
            %else
              &amp;amp;&amp;amp;varname&amp;amp;colno. = "&amp;amp;value";
          %end;
          ;

        %if &amp;amp;sqlobs.=0 %then 
          drop table WORK.ZZ&amp;amp;&amp;amp;memname&amp;amp;memno.; ;

      %end;

    %end;

  quit;

%mend findvalue;

%findvalue(lib=SASHELP, value=Alice);

&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This version is not satisfactory for me as it creates global macro variables.&lt;/P&gt;
&lt;P&gt;I would remedy this point as well before making the macro available.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jul 2019 04:05:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572989#M161731</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2019-07-12T04:05:11Z</dc:date>
    </item>
    <item>
      <title>Re: Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572990#M161732</link>
      <description>&lt;P&gt;Improved version:&lt;/P&gt;
&lt;P&gt;- No macro language&lt;/P&gt;
&lt;P&gt;- Much faster as the dictionary is only queried once&lt;/P&gt;
&lt;P&gt;- Much more resistant to weird values being searched&lt;/P&gt;
&lt;P&gt;- Option for case-sensitive/insensitive comparison&amp;nbsp;&lt;/P&gt;
&lt;P&gt;- More flexible as different comparison operators can be used (EQ or =:&amp;nbsp; or ? for example)&lt;/P&gt;
&lt;P&gt;[Edited to add char/num search option]&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro FindAValue(lib=, type=C, value=, icase=1, comparison=EQ);

  %macro _; %mend _;

  proc sql ;
    create table __FINDAVALUE__ as
    select MEMNAME, NAME
    from DICTIONARY.COLUMNS 
    where LIBNAME eq "&amp;amp;lib " 
      and TYPE    eq %if &amp;amp;type.=C %then 'char'
      and LENGTH  ge %length(%superq(value))
      ; %else 'num' ;
    order by MEMNAME;
    %if ^&amp;amp;sqlobs. %then %do;
      drop table __FINDAVALUE__; quit;
      %return;
    %end;
  quit;

  data _null_;  
    set __FINDAVALUE__ ;
    by MEMNAME;
    if first.MEMNAME then call execute('data ZZ'||MEMNAME||"; set &amp;amp;lib.."||MEMNAME||'; where ');
    else call execute(' or ');
    %if &amp;amp;type.=C &amp;amp; &amp;amp;icase. %then 
      call execute('upcase('||NAME||") &amp;amp;comparison "||upcase(quote(trim(symget('value')))) );
    %else %if &amp;amp;type.=C %then
      call execute(           NAME||"  &amp;amp;comparison "||       quote(trim(symget('value')))   );
    %else 
      call execute(           NAME||"  &amp;amp;comparison "||             trim(symget('value'))    );
    ;
    if last.MEMNAME then call execute(';data _null_;' 
     ||'if NOBS=0 then call execute("proc delete data=ZZ'||MEMNAME||';run;");'
     ||'if 0 then set ZZ'||MEMNAME||' nobs=NOBS; stop; run;');
   run;

   proc delete data=__FINDAVALUE__; run;

%mend FindAValue;
                                                                  
%FindAValue(lib=SASHELP, value=Alice, icase=1, comparison=?);

%FindAValue(lib=SASHELP, value=11,  type=N, comparison=eq);

&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jul 2019 05:28:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572990#M161732</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2019-07-12T05:28:38Z</dc:date>
    </item>
    <item>
      <title>Re: Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572992#M161733</link>
      <description>&lt;P&gt;Well this looked kind of fun &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's my take on it.&amp;nbsp; Perhaps someone can suggest performance improvements but it has acceptable performance on SASHELP.&amp;nbsp; %code1 performs better but can miss hits if you're searching for multiple strings.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'll leave it to you to finish "macro-izing" it, such as wrapping it in a top level macro, case-insensitive search, etc.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Go here to download the macros:&amp;nbsp;&amp;nbsp;&lt;A href="https://github.com/scottbass/SAS/tree/master/Macro" target="_blank" rel="noopener"&gt;https://github.com/scottbass/SAS/tree/master/Macro&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* list of datasets ;
proc sql noprint;
   select catx('.',libname,memname) 
   into   :datasets separated by ' '
   from   dictionary.tables
   where  libname="SASHELP" 
     and  memtype='DATA'
   ;
quit;

%put &amp;amp;datasets;

* macro to process the datasets ;
%macro code1;
data temp;
   length _dataset_ $32 _variable_ $32 _value_ $200 _dsname_ $41;
   set &amp;amp;word indsname=dsname;
   array vars{*} _character_;
   do i=1 to dim(vars);
      if vars{i} in (%seplist(&amp;amp;value,indlm=^,nest=q)) then do;
         _dataset_=dsname;
         _variable_=vname(vars{i});
         _value_=vars{i};
         output;
         stop;
      end;
   end;
   keep _dataset_ _variable_ _value_;
run;
proc append 
   base=results1 
   data=temp (rename=(_dataset_=dataset _variable_=variable _value_=value))
;
run;
%mend;

* Alternative, slower but more complete ;
%macro code2;
data temp;
   length _dataset_ $32 _variable_ $32 _value_ $200 _dsname_ $41;
   set &amp;amp;word indsname=dsname;
   array vars{*} _character_;
   do i=1 to dim(vars);
      if vars{i} in (%seplist(&amp;amp;value,indlm=^,nest=q)) then do;
         _dataset_=dsname;
         _variable_=vname(vars{i});
         _value_=vars{i};
         output;
         * stop;
      end;
   end;
   keep _dataset_ _variable_ _value_;
run;
proc sort noduprecs;
   by _all_;
run;
proc append 
   base=results2 
   data=temp (rename=(_dataset_=dataset _variable_=variable _value_=value))
;
run;
%mend;

%kill(data=results1 results2);

%let value=Ketchikan^New York^Alice^IBM;

* testing ;
/*%loop(sashelp.zipcode,mname=code1)*/

* the whole shebang ;
* note this misses some hits in zipcode because the stop statement stops on the first hit ;
%loop(&amp;amp;datasets,mname=code1)

* alternative approach ;
%loop(&amp;amp;datasets,mname=code2)

&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jul 2019 05:02:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/572992#M161733</guid>
      <dc:creator>ScottBass</dc:creator>
      <dc:date>2019-07-12T05:02:43Z</dc:date>
    </item>
    <item>
      <title>Re: Finding a value in all datasets in all variables - revisited</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/573108#M161757</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13884"&gt;@ballardw&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I like the length addition.&amp;nbsp; Thanks for that.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Yes, adding parameters to the macro was my next step...didn't need them for first version.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The libname is needed because work is the destination library, not the source.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;CATS would work as well but adds nothing.&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jul 2019 14:27:58 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Finding-a-value-in-all-datasets-in-all-variables-revisited/m-p/573108#M161757</guid>
      <dc:creator>tomrvincent</dc:creator>
      <dc:date>2019-07-12T14:27:58Z</dc:date>
    </item>
  </channel>
</rss>

