BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
alepage
Barite | Level 11

Hello, 

 

I am trying to create  new variable using a case when else end as company_cd but it does not work as expected.

 

 

 

data _null_;
   set inforcelisting5;
   call execute
   (compbl(cat(
   "Libname dssource ", engine,'"',path,'";',
   '%nrstr(%macro lookuptbl;)',
   /******************** Mapping few variables *************************************/
   '%nrstr(%global varname1 varname2 varname3 ;)',
   '%nrstr(%if %varexist(dssource.',strip(fname),',police) %then %let varname1=police;)',
   '%nrstr(%else %if %varexist(dssource.',strip(fname),',agreement_nbr) %then %let varname1=agreement_nbr;)',
   '%nrstr(%if %varexist(dssource.',strip(fname),',police) %then %let varname2=datechea;)',
   '%nrstr(%else %if %varexist(dssource.',strip(fname),',agreement_nbr) %then %let varname2=policy_expiry_dt;)',
   '%nrstr(%if %varexist(dssource.',strip(fname),',province) %then %let varname3=province;)',
   '%nrstr(%else %if %varexist(dssource.',strip(fname),',risk_province_cd) %then %let varname3=risk_province_cd;)',
   '%nrstr(%else %if %varexist(dssource.',strip(fname),',policy_province_cd) %then %let varname3=policy_province_cd;)',
   '%nrstr(%else %if %varexist(dssource.',strip(fname),',province_cd) %then %let varname3=province_cd;)',   
   '%nrstr(%put &=varname1 &=varname2 &=varname3;)', 
   /************************ End of Mapping few variables ***************************/
   "proc sql;",
   "create table table_info as ",
   '%nrstr(Select distinct strip(a.&varname1.) as agreement_nbr length=20 )',
   ',"',strip(cie), '"  as cie length=2',
   ',"',strip(lob), '"  as lob length=4',
   ',"',strip(year), '"  as year length=4',
   ',"',strip(fname), '"  as filename length=25',
   ',"',strip(path), '"  as libname length=100 ',   
   '%nrstr(, CASE)',
   '%nrstr(     WHEN "',strip(cie),'" eq "be" then "B" )',
   '%nrstr(     WHEN "',strip(cie),'" eq "gc" then "A" )',
   '%nrstr(     WHEN "',strip(cie),'" eq "gp" then "P" )',
   '%nrstr(     WHEN "',strip(cie),'" not in ("be","gc","gp") then a.company_cd )',
   '%nrstr( END AS COMPANY_CD )',
   '%nrstr(from dssource.',strip(fname),' as  a ; )', 
    "Quit;",
   '%nrstr(%mend lookuptbl;)',
   '%nrstr(%lookuptbl;)',	
   "Libname dssource clear;"
)));
run;

proc sql;

select

case

     when cie eq 'be' then "B"

     when cie eq 'gc' then "A"

    When cie eq 'gp' then "P"

    when cie not in ('be','gc','gp') then a.company_cd

end as company_cd

from ...

innner join...

on()...

Quit;

 

This script should map company_cd properly it does work properly.  Does someone has an idea how to solve that issue

NOTE: CALL EXECUTE generated line.
1 + Libname dssource base"/dwh_actuariat/sasdata/sas2002/be/habi/bel.prod1000.sah1stat.dec2002.data/ ";
NOTE: Libref DSSOURCE was successfully assigned as follows:
Engine: BASE
Physical Name: /dwh_actuariat/sasdata/sas2002/be/habi/bel.prod1000.sah1stat.dec2002.data/
1 + %macro
lookuptbl;%global varname1 varname2 varname3 ;%if %varexist(dssource.polices,police) %then %let varname1=police;%else %if %varexist
2 +(dssource.polices,agreement_nbr) %then %let varname1=agreement_nbr;%if %varexist(dssource.polices,police) %then %let
varname2=datechea;%else %if %varexist(dssource.polices,agreement_nbr) %then %let varname2=policy_expiry_dt;%if %varexist
3 +(dssource.polices,province) %then %let varname3=province;%else %if %varexist(dssource.polices,risk_province_cd) %then
%let varname3=risk_province_cd;%else %if %varexist(dssource.polices,policy_province_cd) %then %let
varname3=policy_province_cd;%else %if
4 + %varexist(dssource.polices,province_cd) %then %let varname3=province_cd;%put &=varname1 &=varname2 &=varname3;proc
sql;create table table_info as Select distinct strip(a.&varname1.) as agreement_nbr length=20 ,"be" as cie length=2,"habi" as lob
5 + length=4,"2002" as year length=4,"polices" as filename
length=25,"/dwh_actuariat/sasdata/sas2002/be/habi/bel.prod1000.sah1stat.dec2002.data/" as libname length=100 , CASE WHEN "be" eq
"be" then "B" WHEN "be" eq "gc" then "A" WHEN "be" eq "gp" then "P"
6 + WHEN "be" not in ("be","gc","gp") then a.company_cd END AS COMPANY_CD from dssource.polices as a ; Quit;%mend
lookuptbl;%lookuptbl;Libname dssource clear;
VARNAME1=police VARNAME2=datechea VARNAME3=province
ERROR: Column company_cd could not be found in the table/view identified with the correlation name A.
NOTE: A CASE expression has no ELSE clause. Cases not accounted for by the WHEN clauses will result in a missing value for the CASE
expression.
NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds

NOTE: Libref DSSOURCE has been deassigned.

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Test the value of CIE in the DATA STEP, not in the SQL code.

Use the data step to only generate the SQL code that includes A.COMPANY_CD when it exists.

 

View solution in original post

6 REPLIES 6
Tom
Super User Tom
Super User

Test the value of CIE in the DATA STEP, not in the SQL code.

Use the data step to only generate the SQL code that includes A.COMPANY_CD when it exists.

 

alepage
Barite | Level 11

I will test that latter during the evening. Thanks

ballardw
Super User

With so many "variable does not exist" errors this is starting to sound like you really don't know your data sets.

 

Is there some terribly important reason that your aren't use an ELSE in  that CASE:

case
     when cie eq 'be' then "B"
     when cie eq 'gc' then "A"
    When cie eq 'gp' then "P"
    else a.company_cd
end as company_cd

Would certainly be  a lot shorter than saying "compare this value to the already compared list and if it is not in that list then do this assignment"

alepage
Barite | Level 11

when cie in (be, gc,gp) the variable company_cd does not exist and I want to map this variable respectively to B, A, P.

When cie is not in (be,gc,gp) the variable company_cd exits and I want to use this value.

ballardw
Super User

@alepage wrote:

when cie in (be, gc,gp) the variable company_cd does not exist and I want to map this variable respectively to B, A, P.

When cie is not in (be,gc,gp) the variable company_cd exits and I want to use this value.


That appears not to be what you wrote in the code and is why you get

ERROR: Column company_cd could not be found in the table/view identified with the correlation name A.

You cannot use a reference to a variable if it does not exist. Period.

So you need something OUTSIDE of the Proc SQL that is checking the value of cie and when it is one of those value you cannot have the CODE with that a.company_cd name referenced.

 

So, describe what that SQL step is supposed to actually do. In some detail.

WHEN clauses assume the variable exists. It appears that is not the actual case from that comment so that SQl really needs a clear cut description of what it is supposed to do. Just like the rest of this code.

Or better, what is the whole process supposed to do and what does that source data set contain.

 

I still don't see any answer to why you though CALL EXECUTE and making multiple versions of the macro was needed in the first place.

Quentin
Super User

This looks like an unusually complex approach.  I enjoy the macro language, and CALL EXECUTE, but I think it's rare to use CALL EXECUTE to execute the code to define a macro. In this case, when the DATA step runs it will generate code to create the macro LOOKUPTBL.  The macro itself has no  parameters but in a sense it's dynamic because you're generating the macro source code dynamically.  If there are 10 records in work.inforcelisting5 you'll create the macro LOOKUPTBL 10 times, and each time it could have a different definition. 

 

I would think this would be easier to design, debug, and maintain if you just define a macro with a few parameters:

 

%macro lookuptbl (data=,varname1=, varname2=, varname3=);
  ...   
%mend;

With that approach you could still use CALL EXECUTE to generate the macro calls, and you could use if VAREXIST to decide which variable names to pass into each macro call.

 

Or if you want to leave the variable exists tests in the macro, you could do it like:

%macro lookuptbl(data);

%local varname1 varname2 varname3;

%if %varexist(&data,police) %then %let varname1=police;
%else %if %varexist(&data,agreement_nbr) %then %let varname1=agreement_nbr;
*...;

%put &=varname1 &=varname2 &=varname3;
   
proc sql;
  create table table_info as
  select distinct
    strip(a.&varname1.) as agreement_nbr length=20
   ,strip(cie) as cie length=2',
   /* ... */
  ;
quit;

%mend lookuptbl;

The idea of dynamically generating macro definitions is kind of scary to me, but I'm sure people do it. Usually macros are dynamic enough, especially when paired with using CALL EXECUTE or similar to generate macro calls.

 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 660 views
  • 1 like
  • 4 in conversation