<?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: Transpose datasets whith sql in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492078#M129262</link>
    <description>&lt;P&gt;Putting aside WHY anyone would want to do that given that SAS already has an optimized PROC for transposing date.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc transpose data=test out=want (drop=_name_) ;
  by id;
  id type ;
  var count;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Which generates a dataset like this:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data work.want ;
  input id gness brehat bt bat ;
datalines4;
111 45 90 90 90
112 45 90 90 .
;;;;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Let's look at your program and offer some tweaks.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note that there is no need to start and stop PROC SQL multiple times. The statements in PROC SQL execute immediately.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There is no need to count the number of observations a SELECT is going to generate. SAS already counts that for you and puts it into the automatic macro variable SQLOBS. Also (unless you are using a really really old version of SAS) here is no need set the upper bound when generating multiple macro variables.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;into :col1 - &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If you are using an old version of SAS then just use a really large number for the upper bound.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;into :col1 - :col999999&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;SAS will only create the macro variables it needs based on the data, no matter what upper bound you set.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also what you want to count is the number of distinct values of TYPE and not ID, since those are the new column names you want to create.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint; 
select distinct type into :col1 - from test;
%let n_type=&amp;amp;sqlobs;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To reduce the multiple observations per ID caused by having different values of TYPE you can use an SQL aggregate function, like MAX().&amp;nbsp; Just use a CASE statement to tell it which values to consider for each output column.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;create table want as
  select id
%do i=1 %to &amp;amp;n_type ;
  ,max(case when type = "&amp;amp;&amp;amp;col&amp;amp;i" then count else . end) as &amp;amp;&amp;amp;col&amp;amp;i
%end;
  from test
  group by 1
  order by 1
;
quit;&lt;/CODE&gt;&lt;/PRE&gt;</description>
    <pubDate>Mon, 03 Sep 2018 17:25:33 GMT</pubDate>
    <dc:creator>Tom</dc:creator>
    <dc:date>2018-09-03T17:25:33Z</dc:date>
    <item>
      <title>Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492075#M129260</link>
      <description>&lt;P&gt;Hello,&amp;nbsp;&lt;/P&gt;&lt;P&gt;I partage this solution of transpose dataset with sql.&lt;/P&gt;&lt;P&gt;What donc you think?&lt;/P&gt;&lt;P&gt;Thank you&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;option mprint mlogic symbolgen;
data test;
input id type $ count;
cards;
111 gness 45
111 brehat 90
111 bt 90
111 bat 90
112 gness 45
112 brehat 90
112 bt 90
 
; run;
 
 
proc sql;
create table test as select * 
from test order by id, type;
quit;
 
 
%macro tt;
 
proc sql noprint; 
 
select count(distinct id) into :n_id
from test;
 
select distinct id  into :col1 -:col%left(&amp;amp;n_id)
 
from test;
 
quit;
 
 
%do i=1 %to &amp;amp;n_id;
     proc sql;
     create table test1&amp;amp;&amp;amp;col&amp;amp;i as
     select id ,type,count , monotonic() as nbr  from test
     where id=&amp;amp;&amp;amp;col&amp;amp;i ; 
 
     proc sql noprint; 
     select count(id) into:n_id_r from test1&amp;amp;&amp;amp;col&amp;amp;i;quit;
     proc sql;
 
     proc sql;
     select distinct (type)  into :type1 -:type%left(&amp;amp;n_id_r)
     from  test1&amp;amp;&amp;amp;col&amp;amp;i;
     quit;
 
     %do j=1 %to &amp;amp;n_id_r;
 
            proc sql;
            create table test_1_&amp;amp;j._&amp;amp;&amp;amp;col&amp;amp;i as
            select id , count as &amp;amp;&amp;amp;type&amp;amp;j. from test1&amp;amp;&amp;amp;col&amp;amp;i
            where nbr=&amp;amp;j.
            ;
 
    %end;
 
 %end;
 
%mend;
 
%tt;
 
data fin ;
merge test_1_:   ;
by id;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;</description>
      <pubDate>Mon, 03 Sep 2018 15:52:32 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492075#M129260</guid>
      <dc:creator>mansour_ib_sas</dc:creator>
      <dc:date>2018-09-03T15:52:32Z</dc:date>
    </item>
    <item>
      <title>Re: Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492078#M129262</link>
      <description>&lt;P&gt;Putting aside WHY anyone would want to do that given that SAS already has an optimized PROC for transposing date.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc transpose data=test out=want (drop=_name_) ;
  by id;
  id type ;
  var count;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Which generates a dataset like this:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data work.want ;
  input id gness brehat bt bat ;
datalines4;
111 45 90 90 90
112 45 90 90 .
;;;;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Let's look at your program and offer some tweaks.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note that there is no need to start and stop PROC SQL multiple times. The statements in PROC SQL execute immediately.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There is no need to count the number of observations a SELECT is going to generate. SAS already counts that for you and puts it into the automatic macro variable SQLOBS. Also (unless you are using a really really old version of SAS) here is no need set the upper bound when generating multiple macro variables.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;into :col1 - &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If you are using an old version of SAS then just use a really large number for the upper bound.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;into :col1 - :col999999&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;SAS will only create the macro variables it needs based on the data, no matter what upper bound you set.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also what you want to count is the number of distinct values of TYPE and not ID, since those are the new column names you want to create.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint; 
select distinct type into :col1 - from test;
%let n_type=&amp;amp;sqlobs;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To reduce the multiple observations per ID caused by having different values of TYPE you can use an SQL aggregate function, like MAX().&amp;nbsp; Just use a CASE statement to tell it which values to consider for each output column.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;create table want as
  select id
%do i=1 %to &amp;amp;n_type ;
  ,max(case when type = "&amp;amp;&amp;amp;col&amp;amp;i" then count else . end) as &amp;amp;&amp;amp;col&amp;amp;i
%end;
  from test
  group by 1
  order by 1
;
quit;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 03 Sep 2018 17:25:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492078#M129262</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2018-09-03T17:25:33Z</dc:date>
    </item>
    <item>
      <title>Re: Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492082#M129263</link>
      <description>&lt;P&gt;Also,from a production environment point of view there has been stupendous effort by&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/13711"&gt;@art297&lt;/a&gt;&amp;nbsp;and his team in creating&amp;nbsp;&lt;A href="http://support.sas.com/resources/papers/proceedings13/538-2013.pdf" target="_blank"&gt;http://support.sas.com/resources/papers/proceedings13/538-2013.pdf&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;which is well worth in term of brevity and convenience. So I would request considering it.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Sep 2018 17:47:29 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492082#M129263</guid>
      <dc:creator>novinosrin</dc:creator>
      <dc:date>2018-09-03T17:47:29Z</dc:date>
    </item>
    <item>
      <title>Re: Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492089#M129266</link>
      <description>&lt;P&gt;As noted, there are easier methods that should be used in SAS. For a quick code review here are some suggestions, but for a production environment you should definitely be using&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;solution.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql noprint; 
 
select count(distinct id) into :n_id
from test;
 
select distinct id  into :col1 -:col%left(&amp;amp;n_id)
 
from test;
 
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This is overkill, you only need :col1- SAS will fill in the last item so you don't need to create that value unless you need it.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql NOPRINT;
select distinct ID into :col1-
from ...
quit;
%let n_id = &amp;amp;sqlobs;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For the step:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;    proc sql;
     create table test1&amp;amp;&amp;amp;col&amp;amp;i as
     select id ,type,count , monotonic() as nbr  from test
     where id=&amp;amp;&amp;amp;col&amp;amp;i ; &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;You would be better off creating a view or using a data set with a specific name. You would also want to delete these temporary data sets so they don't carry over to next runs and so that you don't end up with a huge library.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In this step you have a count, but you should be able to capture it from the previous step using the automatic macro variable SQLOBS.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  proc sql noprint; 
     select count(id) into:n_id_r from test1&amp;amp;&amp;amp;col&amp;amp;i;quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;You may also want to be careful with using naming conventions that are that close, ie&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;TEST_&lt;/P&gt;
&lt;P&gt;TEST1_&lt;/P&gt;
&lt;P&gt;TEST_1&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It's very easy to mix these up and then it becomes really hard to debug at that point.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope these help with what you were trying to learn.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And as shown, these 4 lines replace your 70 lines of code.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As a learning exercise, one place where macros are still required - trying to output a table and graph onto the same page. There's no easy way to use BY groups or a PROC to get around that, though you can use ODS GREPLAY I believe but it's harder to implement.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 03 Sep 2018 18:36:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492089#M129266</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2018-09-03T18:36:26Z</dc:date>
    </item>
    <item>
      <title>Re: Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492101#M129271</link>
      <description>&lt;P&gt;"&lt;EM&gt;As a learning exercise, one place where macros are still required - trying to output a table and graph onto the same page. There's no easy way to use BY groups or a PROC to get around that, though you can use ODS GREPLAY I believe but it's harder to implement.&amp;nbsp;&lt;/EM&gt;"&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I sometimes find ODS LAYOUT useful for the purpose of organizing many tables or graphs on the same page. It only works for some output destinations though.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Sep 2018 18:52:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492101#M129271</guid>
      <dc:creator>PGStats</dc:creator>
      <dc:date>2018-09-03T18:52:56Z</dc:date>
    </item>
    <item>
      <title>Re: Transpose datasets whith sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492235#M129330</link>
      <description>&lt;P&gt;I think it is a rather silly idea (use PROC TRANSPOSE!), but a fun challenge. I would do it like this:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro SqlTrans;
  %local i types ids id set;
  proc sql noprint;
    select distinct(catx(' ',type,'FLOAT')) into :types separated by ','
    from test;
    create table fin(id FLOAT,&amp;amp;types);
    select distinct id into: ids separated by ' ' from test;
    %do i=1 %to &amp;amp;sqlobs;
      %let id=%scan(&amp;amp;ids,&amp;amp;i);
      select cats(type,'=',sum(count)) into :set separated by ','
      from test where id=&amp;amp;id
      group by type;
      insert into fin set id=&amp;amp;id,&amp;amp;set;
      %end;&lt;BR /&gt;  quit;
%mend;
%SqlTrans;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Note that this macro actually manages to declare all created variables local (you can do that with SQLOBS as well, if you want to). And that I managed to keep the whole shebang in SQL, no final data step.&lt;/P&gt;&lt;P&gt;I used SUM(COUNT) and GROUP BY TYPE in case there are duplicates on TYPE within an ID.&lt;/P&gt;</description>
      <pubDate>Tue, 04 Sep 2018 09:35:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Transpose-datasets-whith-sql/m-p/492235#M129330</guid>
      <dc:creator>s_lassen</dc:creator>
      <dc:date>2018-09-04T09:35:10Z</dc:date>
    </item>
  </channel>
</rss>

