2017-01-24 10 views
1

Я не могу решить, решить одну проблему.Цитирование через столы и их соединение в SAS

У меня есть неизвестное количество таблиц в одной библиотеке SAS. Я хочу сделать цикл, который проходит через них и «UNION ALL» эти таблицы.

Столы предварительно проверены и имеют одинаковую структуру. Эти таблицы включают в себя историзированные данные, поэтому он должен быть всем Союзом. Я пробовал следующий скрипт, но он ищет все возможности, но не делает UNION ALL.

Я ценю любые идеи для решения этой проблемы.

%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; 

Заранее спасибо.

+0

Вы делаете «союз все» на 1216 таблицах? Какие сообщения об ошибках вы получаете? Можете ли вы предоставить [воспроизводимый пример] (http://www.stackoverflow.com/help/mcve)? – user667489

+0

1216 - это месяц и год, который идентифицирует каждую таблицу и отличается для каждой таблицы. – Noza

+0

Ошибка: Файл Table_1 не существует. Ужасно: Файл Table_2 не существует. Ошибка: Файл Table_3 не существует. ......и т. д. и окончание объединения не завершено. – Noza

ответ

1

Если: A) общая длина всех ваших файлов + их префикс libname + период < 32767; и B) ваши составные файлы находятся в одной библиотеке; и C) ваши файлы начинаются с «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; 

Для справки, я списаны большую часть этого из Р5 в SUGI 29 бумаги Ричардсон & Rossland.

1

Ваш макрос ищет таблицы с именем table_1 до table_1216 и дает вам сообщение об ошибке, когда он не может найти те, которые не существуют. Вам нужно изменить свой цикл, чтобы он только пытался принять объединение фактически существующих таблиц.

5

Возможно, вы можете отказаться от макроса и использовать инструкцию SET.

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

Если таблицы одинаковы относительно переменных и типа Open = defer может сэкономить много памяти.

+0

Это супер круто. Я знал о: ярлыке для имен переменных, но никогда не думал попробовать его для имен набора данных в инструкции SET. Спасибо за это! –

0

Независимо от того, как ваши наборы данных называются, просто поместить их всех в список после создания переменной порядка и установить их вместе (заменить work. с тем, что ваша библиотека называется):

/* 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

Мне нравится ваш подход в качестве альтернативы основному подходу (шаг данных с подстановочным знаком), но похоже, что вам гораздо проще использовать словар .tables вместо этапа содержимого proc/dedup, тем более, re уже в SQL. – Joe

0

Спасибо всем ваши ответы. Я почти ничего не использовал для достижения нужного мне результата.

Я хочу опубликовать свой собственный результат, потому что использовал частично коды от пользователей Amw 5G и Foxer.

/* 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; 

Таким образом, он объединяет все мои таблицы, даже если существует другая структура. Поскольку таблицы могут меняться с течением времени (некоторые столбцы можно удалить или добавить новые).

Для таблицы proc append должна быть одинаковая структура. Поэтому в моем случае разумно использовать data set.

 Смежные вопросы

  • Нет связанных вопросов^_^