2012-04-10 14 views
1

Wie Makros in SQL verwenden? (Für jedes Ding, das war gewählt)SAS-Makros: Verwenden von Makros in proc sql

ich so etwas wie dies bedeuten:

&VarTable ist eine Tabelle, die zwei Variablen: (zum Beispiel) Lib und Table

Jede Beobachtung in &VarTable ist die Name der Tabelle: Lib.Table

ich möchte für jeden Tisch Dinge tun:

1) gibt es?

2) Sortieren es

und letzte Zustand: Jede Tabelle, wenn sie vorhanden sind, haben eine variable &VarField.

%macro mSortedTable(vLib,vTab,vVar); 
     %if %sysfunc(exist(&vLib..&vTab)) %then %do; 
      proc sort data = &vLib..&vTab; 
       by &vVar; 
      run; 
      &vLib..&vTab 
     %end; 
     %else %do; "" %end; 
    %mend mSortedTable; 

    proc sql noprint; 
      select %mSortedTable(vLib=Lib,vTab=Table,vVar=&VarField) 
       into: AccumVar separated by " " 
      from &VarTable; 
    quit; 

wie mit sql und macros?

+0

Ausweichen erste Frage: Dieser Code funktioniert nicht, natürlich – gaussblurinc

+0

so mit einem Datensatz, die Erklärungen der Bibliothek enthält und die Datensatznamen möchten Sie Aktionen ausführen auf jedem Datensatz? und Sie möchten jeden Variablennamen in ein Makro einfügen? –

+0

ja. mein Kollege sagte mir, dass ich das tun kann, mit Katzen und Makrogeneration: proc sql noprint; 'selektiere Katzen ('% mSortedTable (', Lib, ',', Table, ',', & VarField, ')') in: AccumVar getrennt durch" " aber diese Variante kann nicht in datastep verwendet werden, so dass i entschied sich, die gleiche Konstruktion mit zwei Makros zu verwenden, wird zuerst sortieren, ein anderer wird Name 'Lib.Table' setzen – gaussblurinc

Antwort

2

Müssen Sie SQL und Makros verwenden? Ein einfacher Datenschritt und call execute würde tun, was Sie hier brauchen.

Unten finden Sie ein Beispiel, das einen Datensatz mit einer Liste von zu verarbeitenden Tabellen verwendet, überprüft, ob die Tabelle vorhanden ist, und falls dies der Fall ist, sortiert sie nach & VarField. Dies könnte leicht erweitert werden, um jede Tabelle bei Bedarf nach einem benutzerdefinierten Satz von Variablen zu sortieren.

Wenn die Tabelle nicht existiert, wird eine Warnmeldung generiert.

/* create fake data */ 
data testdat; 
length lib $8 table $32; 
input lib $ table $; 
datalines; 
work test1 
work test2 
work test3 
work doesnotexist 
; 
run; 
/* create 3 data sets */ 
data work.test1 work.test2 work.test3; 
input var1 var2 var3; 
datalines; 
1 34 8 
2 54 5 
12 5 6 
; 
run; 
/* end create data */ 

%let VarTable=work.testdat; 
%let VarField=var2 var3; 


data _null_; 
    set &VarTable; 
    dsname=catx('.',lib,table); 
    if exist(dsname) then do; 
    call execute("proc sort data=" || strip(dsname) || "; by &VarField; run;"); 
    end; 
    else do; 
    put "WARNING: The data set does not exist: " lib= table=; 
    end; 
run; 
+0

hmm .. du hättest einfachen Code geschrieben :) aber ich kann nicht verstehen, wenn dieser Code funktioniert, wie es funktionieren sollte mich. Ich verwirrt über die Verwendung von Makro in Ihrem Code, bitte, sagen, ist 'Call Execute' Arbeit wie' eval' Funktion in Sprachen wie Perl-PHP-js? – gaussblurinc

+0

Ja, es ähnelt einem perl 'eval', SAS analysiert die Zeichenfolge und übergibt den analysierten Code dann wie eine SAS-Sitzung. Da der Datenschritt zeilenweise ausgeführt wird, wird die "Aufrufausführung" einmal pro Datenzeile gesendet, die der if-Bedingung entspricht. – cmjohns

1

Anruf auszuführen ist eine gute Lösung, aber wenn der Daten Schritt Code „ausgeführt“ wird kompliziert ist (was es nicht in diesem Beispiel ist), habe ich es schwer zu debuggen finden.

Eine andere Methode besteht darin, alle Variablen in Makrovariablen zu setzen und sie dann in einer Makro-Do-Schleife durchzulaufen;

(aufbauend auf @cmjohns Daten)

/* create fake data */ 
data testdat; 
length lib $8 table $32; 
input lib $ table $; 
datalines; 
work test1 
work test2 
work test3 
work doesnotexist 
; 
run; 

/* create 3 data sets */ 
data work.test1 work.test2 work.test3; 
input var1 var2 var3; 
datalines; 
1 34 8 
2 54 5 
12 5 6 
; 
run; 
/* end create data */ 

%let VarTable=work.testdat; 
%let VarField=var2 var3; 

proc sql noprint; 
select count(lib) 
into :cnt 
from &vartable; 

%Let cnt=&cnt; 

select strip(lib), strip(table) 
into :lib1 - :lib&cnt, :table1 - :table&cnt 
from &vartable; 
quit; 

%Macro test; 
%Do i = 1 %to &cnt; 

    %Let lib=&&lib&i; 
    %Let table=&&table&i; 
    %Let dsn=&lib..&table; 

    %if %sysfunc(exist(&dsn)) %then %do; 
    Proc sort data=&dsn; 
    by &varfield; 
    run; 
    %end; 
    %else %do; 
    %put WARNING: The data set does not exist: &dsn; 
    %end; 

%end; 
%Mend; 
%test