2010-11-11 17 views
5

Ich habe 2 Makros, die ich versuche, 1 nach dem anderen wie eine Schleife mit einer Metadatentabelle und den Aufruf ausführen Befehl in einem Datenschritt auszuführen.Makrovariablen Problem bei der Verwendung von Call execute

Makro% TWO erfordert die globale Variable & names_agg. das soll im Makro% ONE erstellt werden. Im folgenden Code ist & Names_agg jedoch das erste Mal leer, wenn ich es ausführe. Wenn ich es erneut ausführe, behält es nur den Wert vom letzten Mal bei, wenn es ausgeführt wird.

Die Idee ist, dass jedes Mal, wenn% ONE ausgeführt wird, eine neue & names_agg. geschaffen.

Was mache ich falsch?

Dank

%macro ONE(condition); 
%global names_agg; 
%let names_agg = ; 

proc sql; 
    select 
     cats(name,"_agg"), 
    into 
     :names_agg separated by " ", 
    from dataset 
    where condition = "&condition." 
    ; 
quit; 
%mend; 

%macro TWO(name_OT); 

data &name_OT.; 
    set &names_agg.; 
run; 

%mend; 

data _null_; 
    length code $32767; 
    set meta_table; 
    code = "%ONE(" || cats(condition) || "); %TWO(" || cats(Name_OT) || ");"; 
    call execute(code); 
run; 

Sorry über das unordentliche Protokoll, das ist der eigentliche Code. Das Problem ist mit NAMES_AGG_A _B und _C nicht korrekt Lösung

871 data test; 
872 length code $32767; 
873 set c.new_name_OT (obs=1); 
874 code = '%OT_Append(' || cats(portfolio) || ',' || cats(scorecard) || ',' || 
874! cats(event_table) || ',' || 
875   cats(scorecard_type) || ',' || cats(obs_period) || ',' || cats(outcome_period) || 
875! ',' || cats(x_var) || 
876   ',' || cats(y_var) || ',' || cats(use) || ',' || cats(condition) || '); %put 
876! &names_agg_a.; %OT_Append2(' || cats(Name_OT) || ');'; 
877 call execute(code); 
878 run; 

MLOGIC(OT_APPEND): Beginning execution. 
MLOGIC(OT_APPEND): Parameter PORTFOLIO has value MTG 
MLOGIC(OT_APPEND): Parameter SCORECARD has value A 
MLOGIC(OT_APPEND): Parameter EVENT_TABLE has value event_table_name 
MLOGIC(OT_APPEND): Parameter SCORECARD_TYPE has value Application 
MLOGIC(OT_APPEND): Parameter OBS_PERIOD has value 1 
MLOGIC(OT_APPEND): Parameter OUTCOME_PERIOD has value 18 
MLOGIC(OT_APPEND): Parameter X_VAR has value PI 
MLOGIC(OT_APPEND): Parameter Y_VAR has value GB_Odds 
MLOGIC(OT_APPEND): Parameter USE has value Development 
MLOGIC(OT_APPEND): Parameter CONDITION has value 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_A) 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_B) 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_C) 
MPRINT(OT_APPEND): proc sql; 
SYMBOLGEN: Macro variable PORTFOLIO resolves to MTG 
SYMBOLGEN: Macro variable SCORECARD resolves to A 
SYMBOLGEN: Macro variable EVENT_TABLE resolves to event_table_name 
SYMBOLGEN: Macro variable SCORECARD_TYPE resolves to Application 
SYMBOLGEN: Macro variable OBS_PERIOD resolves to 1 
SYMBOLGEN: Macro variable OUTCOME_PERIOD resolves to 18 
SYMBOLGEN: Macro variable X_VAR resolves to PI 
SYMBOLGEN: Macro variable Y_VAR resolves to GB_Odds 
SYMBOLGEN: Macro variable USE resolves to Development 
SYMBOLGEN: Macro variable CONDITION resolves to 
MPRINT(OT_APPEND): select cats("c.",name,"_agg_a"), cats("c.",name,"_agg_b"), 
cats("c.",name,"_agg_c") into :names_agg_a separated by " ", :names_agg_b separated by " ", 
:names_agg_c separated by " " from c.datasets_pit where portfolio = "MTG" and scorecard = "A" 
and event_table = "event_table_name" and scorecard_type = "Application" and obs_period = 1 and 
outcome_period = 18 and x_var = "PI" and y_var = "GB_Odds" and use = "Development" and 
condition = "" ; 
MPRINT(OT_APPEND): quit; 
MLOGIC(OT_APPEND): Ending execution. 
SYMBOLGEN: Macro variable NAMES_AGG_A resolves to 

Im Wesentlichen das Problem ist hier, die obige Aussage Put in dem Aufruf ausführen zeigt, dass NAMES_AGG_A nichts auflöst.

NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 

MLOGIC(OT_APPEND2): Beginning execution. 
MLOGIC(OT_APPEND2): Parameter NAME_OT2 has value MTG_Dev_OT_1 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_ODDS; 
SYMBOLGEN: Macro variable NAMES_AGG_A resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_GINI; 
SYMBOLGEN: Macro variable NAMES_AGG_B resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_DIST; 
SYMBOLGEN: Macro variable NAMES_AGG_C resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
MLOGIC(OT_APPEND2): Ending execution. 
NOTE: There were 1 observations read from the data set C.NEW_NAME_OT. 
NOTE: The data set WORK.TEST has 1 observations and 12 variables. 

NOTE: CALL EXECUTE generated line. 
1 +  proc sql; 
1 +       select    cats("c.",name,"_agg_a"), 
cats("c.",name,"_agg_b"),    cats("c.",name,"_agg_c")   into 
:names_agg_a separated by " ",    :names_agg_b separated by " ", 
2 + :names_agg_c separated by " "   from c.datasets_pit    where portfolio = 
"MTG" and     scorecard = "A" and     event_table = "event_table_name" 
and     scorecard_type = "Application" and 
3 + obs_period = 1 and     outcome_period = 18 and     x_var = "PI" 
and     y_var = "GB_Odds" and     use = "Development" and 
    condition = ""   ;  quit;; data c.MTG_Dev_OT_1_ODDS;  set 
NOTE: PROCEDURE SQL used (Total process time): 
     real time   0.01 seconds 
     cpu time   0.00 seconds 


4 + ; run; 

NOTE: There were 1 observations read from the data set WORK.TEST. 
NOTE: The data set C.MTG_DEV_OT_1_ODDS has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 


4 +   data c.MTG_Dev_OT_1_GINI;  set ; run; 

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_ODDS. 
NOTE: The data set C.MTG_DEV_OT_1_GINI has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 


4 +             data c.MTG_Dev_OT_1_DIST;  set ; run; 

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_GINI. 
NOTE: The data set C.MTG_DEV_OT_1_DIST has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 

Antwort

7

Sie können Makroaufrufe mit %nrstr() verzögern, dann funktioniert es gut.

/* test data */ 
    data dataset; 
    name="a"; condition="1"; output; 
    name="b"; condition=" "; output; 
    name="c"; condition="1"; output; 
    run; 

    data a_agg; v="a_agg"; run; 
    data b_agg; v="b_agg"; run; 
    data c_agg; v="c_agg"; run; 

    data meta_table; 
    condition="1"; name_ot="ot1"; output; 
    condition="2"; name_ot="ot2"; output; 
    condition=" "; name_ot="ot_"; output; 
    run; 

    %macro one(condition); 
    %global names_agg; 
    %let names_agg = ; 
    proc sql noprint; 
     select cats(name,"_agg") into :names_agg separated by " " 
     from dataset where condition = "&condition."; 
    quit; 
    %mend; 

    %*-- just checking --*; 
    %one(condition=1) %put names_agg=&names_agg; 
    %one(condition=2) %put names_agg=&names_agg; 
    %one(condition=) %put names_agg=&names_agg; 
    %*-- on log 
    names_agg=a_agg c_agg 
    names_agg= 
    names_agg=b_agg 
    --*; 

    %macro two(name_ot); 
    %if &names_agg= %then %do; 
     data &name_ot.; run; 
    %end; %else %do; 
     data &name_ot.; 
     set &names_agg.; 
     run; 
    %end; 
    %mend; 

    data _null_; 
     length code $200; 
     set meta_table; 
     code = catt('%one(', condition, ")"); 
     code = catt(code, '%two(', name_ot, ")"); 
     code = catt('%nrstr(', code, ")"); 
     call execute(code); 
    run; 

    /* check */ 
    title ot1; proc print data=ot1; run; title; 
    /* on lst 
    ot1 
    Obs  v 
    1  a_agg 
    2  c_agg 
    */ 
    title ot2; proc print data=ot2; run; title; 
    /* on log 
    NOTE: No variables in data set WORK.OT2. 
    */ 
    title ot_; proc print data=ot_; run; title; 
    /* on lst 
    ot_ 
    Obs  v 
    1  b_agg 
    */ 
+0

Danke Chang! Ich habe gerade% nrstr zu meinem Code hinzugefügt und es hat mein Problem gelöst! – MarkG

0

Es sei denn, Sie haben eine Menge von den Makros für das Beispiel, das Sie geschrieben haben, verglichen zurück, dann ist es schwer zu sehen, warum diese mit zwei Makros tun würde, anstatt nur eine (oder in der Tat, warum du würdest verwenden von Makros dies überhaupt), wie dies zu tun:

%macro TheOnlyOne(condition,name_OT); 
    proc sql noprint; 
    select cats(name,"_agg") 
    into :names_agg separated by " " 
    from dataset 
    where condition="&condition"; 
    quit; 
    data &name_OT; 
    set &names_agg; 
    run; 
%mend; 

wie dem auch sei, wrt Ihre Frage, was usw. mit den Makrovariablen zwischen den Anrufen los ist, haben Sie

  • Ausführen der Makros versucht nacheinander außerhalb des Anrufs e xecute Methode?
  • Einstellung options mprint mlogic symbolgen; vor der Ausführung Debugging-Informationen im Protokoll zu sehen?
  • Verwenden Sie einige %put Anweisungen in Ihren Makros, und put Anweisungen in Ihrem call execute datastep, um zu sehen, was an verschiedenen Punkten generiert wird?

Es ist ratsam, wenn Macro-Anwendungen entwickeln zunächst ohne den Code zu erhalten läuft überhaupt mit Makro, dann Makrovariablen hinzufügen und explizit %let -ting ihre Werte, dann ist es im Rahmen eines Makros zu testen. Umzug nach call execute wäre danach.

Vielleicht versuchen Sie ein paar der oben genannten Punkte und kommen mit einigen Log-Ausgabe zurück, die wir debuggen können. Es gibt ein paar andere Fehler/Probleme in dem Code, den Sie gepostet haben, aber anstatt sie darauf hinzuweisen, gehe ich davon aus, dass Sie es für den SO-Post zurückgeben.

BTW Ich mag die Idee der Fahrt datengesteuerten Code mit data _null_ mit call execute, verwende ich diesen Ansatz eine Menge.

+0

Hallo sasfrog, ich habe zunächst ein einzelnes Makro verwenden, das funktioniert, wenn nur das Makro normalerweise ausgeführt wird, aber innerhalb des Anrufs führen Sie die & name_agg Variable leer ist das erste Mal, es läuft, aber den Wert des letzten Laufs hat, wenn führe es nochmals aus. – MarkG

+0

Aus diesem Grund habe ich es in 2 Makros geteilt, die denken, dass es & names_agg auflöst, wenn Makro EINS endet, damit es in Makro ZWEI verwendet werden kann. Auch dies läuft normal, aber das gleiche Problem existiert in der Call Execute. Es scheint, dass die & name_agg -Variable nur am Ende der Aufrufausführung aufgelöst wird, d. H. Sie kann die Makros x-mal ausführen, abhängig von dem, was ich in der Metadatentabelle spezifiziert habe, sondern nur die letzte & name_agg, nachdem alle Makros abgeschlossen sind. – MarkG

+0

@MarkG, alles, was ich vorschlagen kann ist, dass Sie die Makro-Debugging-Techniken in meinem Beitrag aufgeführt, und vielleicht führen Sie die 'data_null_' Schritt mit' obs = 1', so dass es nur einmal ausgeführt wird. Dann werden wir ein Protokoll haben, um es zu untersuchen. Und tun Sie definitiv, was @Rob mit einfachen Anführungszeichen vorschlägt. – sasfrog

1

Sie müssen wahrscheinlich die doppelten Anführungszeichen zu einfachen Anführungszeichen in Ihrem datastep wie so ändern:

data _null_; 
    length code $32767; 
    set meta_table; 
    code = '%ONE(' || cats(condition) || '); %TWO(' || cats(Name_OT) || ");"; 
    call execute(code); 
run; 

Momentan befindet sich der Makro-Prozessor versucht, die Prozentzeichen in der 3. Zeile zu lösen. Sie können dies verhindern, indem Sie sie in einfachen Anführungszeichen verbergen.

+0

Hallo Rob, ich habe versucht, einzelne Anführungszeichen wie Sie vorgeschlagen, aber das Problem besteht immer noch. Grundsätzlich wird & names_agg nicht erstellt, bevor das Makro TWO ausgeführt wird. Danke für deine Antwort! – MarkG

+0

+1 für dich @Rob - wie habe ich das vermisst? :) – sasfrog

Verwandte Themen