<?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: Add rows when month doesn't exist in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764208#M242033</link>
    <description>&lt;P&gt;I agree with&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;comment that this is a situation in which SQL implementation of cartesian joins is a syntactical advantage.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But of course, cartesian join essentially means comparing every row in the left table against every row in the right table, which can be costly if the tables are big.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If data set HAVE is sorted by ID/MONTH, you can add some complexity to the program to avoid the cartesian comparison and possibly save significant resources.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*First, build a comma-separated list of valid month values in macrovar MONTHS_LIST*/
proc sql noprint;
  select month into :months_list separated by ',' from helpmonths;
  %let n_months=&amp;amp;sqlobs;
quit;
%put &amp;amp;=n_months;
%put &amp;amp;=months_list;


/* Now read each ID twice, first time to identify found month, */
/* second time to output records*/
data want (drop=_:);

  array mlist {&amp;amp;n_months} _temporary_ (&amp;amp;months_list);
  array _found{&amp;amp;n_months} $1 ;

  do until (last.id);
    retain _sentinel1 .;
    set have;
    by id;
    retain _sentinel2 .;
 
    _found{whichn(month,of mlist{*})}='Y'; 
  end;

  _temp_id=id;
  do _m=1 to dim(mlist);
    if _found{_m}='Y' then set have;
    else call  missing(of _sentinel1--_sentinel2);
    id=_temp_id;
    month=mlist{_m};
    output;    
  end;
run;

&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;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Thu, 26 Aug 2021 16:04:42 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2021-08-26T16:04:42Z</dc:date>
    <item>
      <title>Add rows when month doesn't exist</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764146#M242016</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;
&lt;P&gt;I have 2 data sets :&lt;/P&gt;
&lt;P&gt;Data set "Have" with 3 columns: ID, month, Y&lt;/P&gt;
&lt;P&gt;Data set Help_tbl with one column: month&lt;/P&gt;
&lt;P&gt;I want to add for each ID in data set "Have" rows for months that are not existing there.&lt;/P&gt;
&lt;P&gt;For example:&lt;/P&gt;
&lt;P&gt;For ID=1 will add 4 rows with months&amp;nbsp; values : 2012, 2106,2107,2108&lt;/P&gt;
&lt;P&gt;For ID=2 will add 4 rows with months&amp;nbsp; values : 2012, 2104,2105,2106,2107,2108&lt;/P&gt;
&lt;P&gt;For ID=3 will add 4 rows with months&amp;nbsp; values : 2012, 2101,2102,2103,2106,2107,2108&lt;/P&gt;
&lt;P&gt;The values of Y available will be null in the rows that I added.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Wanted data set is :&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Ronein_0-1629975603293.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/63046iEEAEB018F73D92B3/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Ronein_0-1629975603293.png" alt="Ronein_0-1629975603293.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The following code that I wrote doesn't give the desired result(As you can see)&lt;/P&gt;
&lt;P&gt;Any help please?&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;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
Data Helpmonths;
input month;
cards;
2012
2101
2102
2103
2104
2105
2106
2107
2108
;
run;

Data have;
input id month Y;
cards;
1 2101 10
1 2102 30
1 2103 20
1 2104 40
1 2105 20
2 2101 15
2 2102 20
2 2103 10
3 2104 30
3 2105 40
;
Run;

proc sort data=Helpmonths; by  month;
Run;
proc sort data=have; by  month;
Run;
Data wanted  ;
Retain ID month  Y;
merge Helpmonths(in=a)have(in=b);
by month;
if a;
Run;
proc sort data=wanted;by ID month;Run;&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;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 26 Aug 2021 11:01:15 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764146#M242016</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2021-08-26T11:01:15Z</dc:date>
    </item>
    <item>
      <title>Re: Add rows when month doesn't exist</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764151#M242020</link>
      <description>&lt;P&gt;Hello&lt;/P&gt;
&lt;P&gt;I wrote good solution and I wonder to see also other solutions, thanks&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data have;
input id month Y;
cards;
1 2101 10
1 2102 30
1 2103 20
1 2104 40
1 2105 20
2 2101 15
2 2102 20
2 2103 10
3 2104 30
3 2105 40
;
Run; 


Data Helpmonths;
input month;
cards;
2012
2101
2102
2103
2104
2105
2106
2107
2108
;
run;
 

PROC SQL;
	create table Help2_tbl  as
	select a.month,b.ID 	   
	from  Helpmonths as a,
	(select distinct ID from have) as b
	order by b.ID,a.month
;
QUIT;



proc sort data=Help2_tbl; by  ID month;
Run;
proc sort data=have; by  ID month;
Run;
Data wanted  ;
Retain ID month  Y;
merge Help2_tbl(in=a)have(in=b);
by ID month;
if a;
Run;
proc sort data=wanted;by ID month;Run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 26 Aug 2021 11:31:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764151#M242020</guid>
      <dc:creator>Ronein</dc:creator>
      <dc:date>2021-08-26T11:31:01Z</dc:date>
    </item>
    <item>
      <title>Re: Add rows when month doesn't exist</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764156#M242022</link>
      <description>&lt;P&gt;This is where SQL and its ability to build cartesian joins comes into its own:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
create table all as
  select distinct have.id, helpmonths.month
  from have, helpmonths
;
create table want as
  select
    all.id,
    all.month,
    have.y
  from all left join have
  on all.id = have.id and all.month = have.month
  order by id, month
;
quit;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 26 Aug 2021 11:40:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764156#M242022</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2021-08-26T11:40:45Z</dc:date>
    </item>
    <item>
      <title>Re: Add rows when month doesn't exist</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764208#M242033</link>
      <description>&lt;P&gt;I agree with&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;comment that this is a situation in which SQL implementation of cartesian joins is a syntactical advantage.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But of course, cartesian join essentially means comparing every row in the left table against every row in the right table, which can be costly if the tables are big.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If data set HAVE is sorted by ID/MONTH, you can add some complexity to the program to avoid the cartesian comparison and possibly save significant resources.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*First, build a comma-separated list of valid month values in macrovar MONTHS_LIST*/
proc sql noprint;
  select month into :months_list separated by ',' from helpmonths;
  %let n_months=&amp;amp;sqlobs;
quit;
%put &amp;amp;=n_months;
%put &amp;amp;=months_list;


/* Now read each ID twice, first time to identify found month, */
/* second time to output records*/
data want (drop=_:);

  array mlist {&amp;amp;n_months} _temporary_ (&amp;amp;months_list);
  array _found{&amp;amp;n_months} $1 ;

  do until (last.id);
    retain _sentinel1 .;
    set have;
    by id;
    retain _sentinel2 .;
 
    _found{whichn(month,of mlist{*})}='Y'; 
  end;

  _temp_id=id;
  do _m=1 to dim(mlist);
    if _found{_m}='Y' then set have;
    else call  missing(of _sentinel1--_sentinel2);
    id=_temp_id;
    month=mlist{_m};
    output;    
  end;
run;

&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;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 26 Aug 2021 16:04:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Add-rows-when-month-doesn-t-exist/m-p/764208#M242033</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-08-26T16:04:42Z</dc:date>
    </item>
  </channel>
</rss>

