2017-01-24 3 views
1

Ich kann nicht herausfinden, um ein Problem zu lösen.Schleifen durch Tabellen und verbinden sie in SAS

Ich habe unbekannte Anzahl von Tabellen in einer SAS-Bibliothek. Ich möchte eine Schleife machen, die durch sie geht und "UNION ALL" diese Tabellen.

Tabellen sind vorgeprüft und haben dieselbe Struktur. Diese Tabellen enthalten historisierte Daten, daher sollte es Union Union sein. Ich habe folgendes Skript versucht, aber es sucht nach allen Möglichkeiten, aber macht UNION ALL nicht.

Ich schätze jede Idee, um dies zu lösen.

%macro union_tables(table_name, last_extract); 
%do i=1 %to &last_extract.; 
     select * from data.&table_name&i 
     union all 
%end; 
     select * from data.&table_name&i 
%mend; 

proc sql; 
create table Full_history as 
%union_tables(Table_,1216); 
quit; 

Vielen Dank im Voraus.

+0

Sie machen eine "Union all" auf 1216 Tabellen? Welche Fehlermeldungen erhalten Sie? Können Sie ein [reproduzierbares Beispiel] (http://www.stackoverflow.com/help/mcve) bereitstellen? – user667489

+0

1216 ist der Monat und das Jahr, die jede Tabelle identifiziert und für jede Tabelle unterschiedlich ist. – Noza

+0

Fehler: Datei Tabelle_1 ist nicht vorhanden. Fehler: Datei Tabelle_2 ist nicht vorhanden. Fehler: Datei Tabelle_3 existiert nicht. ......und so weiter und es wird keine Vereinigung mehr gemacht – Noza

Antwort

1

Wenn: A) die Gesamtlänge aller Ihre Dateinamen + ihre libname Präfix + Zeitraum ist < 32767; und B) Ihre konstituierenden Dateien befinden sich alle in einer Bibliothek; und C) Ihre Dateien beginnen alle mit ‚Table_‘

data _null_; 
length datasets $32767; *make sure this is long enough to hold all your dataset names + their libname prefix. 32767 is the max string length; 
retain datasets; 
set sashelp.vstable end=eof; *This system view holds all known datasets in all known libraries; 
where upcase(libname)='DATA'; *The libname where you dsets live. Use all uppercase; 
if index(UPCASE(memname),'TABLE_') =1 /*Your code shows all datasets begin with 'Table_'*/ then 
datasets=trim(datasets)|| 
' '||trim(libname)|| 
'.'||trim(memname); 
if eof then call symput('datasets',datasets); 
run; 
%put &datasets; *print them to the log; 

data all_the_datasets; 
set &datasets; 
run; 

Als Referenz ich cribbed viel davon von p5 eines SUGI 29 Papier von Richardson & Rossland.

1

Ihr Makro sucht nach Tabellen mit den Namen table_1 bis table_1216 und gibt Ihnen einen Fehler, wenn es die nicht vorhandenen nicht finden kann. Sie müssen Ihre Schleife so ändern, dass sie nur versucht, die Vereinigung von tatsächlich vorhandenen Tabellen zu übernehmen.

5

Vielleicht könnten Sie auf Makro verzichten und die SET-Anweisung verwenden.

data Many; 
    set table_: open=defer; 
    run; 

Wenn die Tabellen in Bezug auf Variablen und Typ identisch sind, kann Open = defer eine Menge Speicher speichern.

+0

Das ist super cool. Ich wusste über die: Verknüpfung für Variablennamen, aber nie gedacht, es für Dataset-Namen in einer SET-Anweisung zu versuchen. Danke dafür! –

0

Egal, wie Ihre Datensätze genannt werden, setzen sie einfach alle in eine Liste nach Auftrag Variable erstellen und setzen sie zusammen (ersetzen work. mit dem, was der Bibliothek benannt):

/* put all dataset names into a dataset */ 
proc contents data = work._all_ noprint out=ds_names(keep=memname); run; 

/* dedupe the dataset and create an order variable */ 
data ds_names1; set ds_names; 
    by memname; 
    if first.memname; 
    order_var + 1; 
run; 

/* put the ordered datasets into a macro variable list */ 
proc sql noprint; 
    select distinct(memname) 
    into: ds_list separated by " " 
    from ds_names1 
    order by order_var; 
quit; 

%put &ds_list.; 

/* append all the datasets together in order */ 
%macro append_instead_of_set(ds_list); 
%do i=1 %to %sysfunc(countw(&ds_list.)); 
    %let ds = %scan(&ds_list.,&i.); 
    proc append data = &ds. base=full force; run; 
%end; 
%mend; 

%append_instead_of_set(&ds_list.); 
+0

Ich mag Ihren Ansatz als Alternative zum Hauptansatz (Datenschritt mit Platzhalter), aber es scheint, als hätten Sie viel leichter '' dictionary.tables' 'anstelle des proc-Inhalts/Deduplizierungsschritts, besonders da Sie' schon in SQL. – Joe

0

Danke alle für deine Antworten. Ich verwendete wenig von allen, um das Ergebnis zu erreichen, das ich brauchte.

Ich möchte mein eigenes Ergebnis veröffentlichen, weil ich teilweise Codes von Amw 5G und Foxer Benutzer verwendet habe.

/* get list of the tables */ 

%MACRO SHOW_TABLES(libname, regex); 
proc sql noprint; 
select memname 
into :list_tables separated by " " 

from dictionary.tables 
where libname="&libname." and upcase(memname) like upcase("%quote(%%)&&regex%") 
order by memname; 
quit; 

%MEND; 

%show_tables(DATA, Table_); 

%put LIST OF TABLES: &list_tables.; 

/* putting data sets together*/ 
DATA data.Full_history; 
SET data.&list_tables.; 
RUN; 

Auf diese Weise fügt es alle meine Tabellen zusammen, auch wenn es eine andere Struktur gibt. Weil sich Tabellen im Laufe der Zeit ändern können (einige Spalten können gelöscht oder neue hinzugefügt werden).

Für die proc append Tabelle sollte die gleiche Struktur haben. Daher ist es in meinem Fall sinnvoll, zu verwenden.