שלום,
איך ניתן לסנן לפני המיזוג רק קבצים שיש בהם מידע - רשומות?
אני רוצה למזג עשרות של קבצים כאשר לעתים יש בהם מידע ולעתים לא.
בדקתי את האופציות שרשומות בפורום באנגלית והם לא נותנות לי מענה שאני מצליחה ליישם.
שלום @Yul
השליפה ב SQL מייצרת משתנה מאקרו של SAS שמכיל את התוצאה של ה SELECT. במקרה שלך משתנה המאקרו שנקרא NAMES מכיל את שמות כל הטבלאות שנמצאות ב Library שמופיע בפקודת ה WHERE.
אנסה להסביר: יש ב SAS טבלאות שנקראות טבלאות dictionary שהן מובנות ב SAS. טבלאות אלה מתעדכנות אוטומטית בכל פעם שעושים Libname או מייצרים קובץ SAS חדש או מוחקים קובץ SAS וכד'.
ה SQL בעצם שולף מאותו dictionary (במקרה זה) את רשימת קבצי ה SAS שנמצאים *כרגע* בספריה שמופיעה בפקודת ה WHERE (ללא פקודת ה WHERE נקבל את רשימת כל קבצי ה SAS בכל ה Libnames) ושומר את התוצאה = רשימת קבצי ה SAS במשתנה מאקרו. אח"כ אפשר להשתמש במשתנה המאקרו הזה בכל מקום שרוצים לדוגמה בפקודת merge ב data step שמופיע מיד לאחר ה SQL.
האם עניתי לשאלה?
היי יוליה,
עשיתי שילוב בין
https://communities.sas.com/t5/SAS-Programming/Delete-empty-datasets-from-work-lib/td-p/103874
וגם
https://communities.sas.com/t5/SAS-Programming/Merge-all-datasets-in-library/td-p/97413
ויצרתי את הדוגמית מטה (אנא תבדקי האם זה עוזר)
בברכה
אריאל
/* creating library and 3 datasets as example*/
libname YUL "C:\temp";
data yul.class1 ;
set sashelp.class;
run;
data yul.a;
set sashelp.class;
name1="אריאל";
run;
data yul.class2;
num=.;
Name='';
run;
/* if your datasets begin with same letters */
/* data want;*/
/* merge c:;*/
/* by name;*/
/* run;*/
/* begin with different letters */
proc sql noprint;
select memname into : names
from dictionary.tables
where libname='YUL' and nobs ne 0; /* note: libname must be in upcase */
data yul.final;
merge &names ;
by name;
run;
היי אריאל,
את החלק הראשון אני כבר מיישמת. את החלק השני של הSQL לא לגמרי מבינה. תוכל לרשום בבקשה ליד כל שורה בפקודת הSQL מה היא אמורה לעשות ומה צריך לשנות שם.
יצרתי מספר מיזוגים של קבצים שמתחילים באותן תחיליות ושמרתי אותם עם תחילית all_name - הNAME משתנה ושמרתי אותם בספריה lib.
proc sql noprint;
select memname into : names
from dictionary.tables
where libname='YUL' and nobs ne 0; - אני מניחה שהYUL זה הLIB
אבל מה אמורים להיות הפרמטרים שאני מכניסה לפקודה המודגשת בקו תחתון?
data yul.final;
merge &names ;
by name;
run;
שלום @Yul
השליפה ב SQL מייצרת משתנה מאקרו של SAS שמכיל את התוצאה של ה SELECT. במקרה שלך משתנה המאקרו שנקרא NAMES מכיל את שמות כל הטבלאות שנמצאות ב Library שמופיע בפקודת ה WHERE.
אנסה להסביר: יש ב SAS טבלאות שנקראות טבלאות dictionary שהן מובנות ב SAS. טבלאות אלה מתעדכנות אוטומטית בכל פעם שעושים Libname או מייצרים קובץ SAS חדש או מוחקים קובץ SAS וכד'.
ה SQL בעצם שולף מאותו dictionary (במקרה זה) את רשימת קבצי ה SAS שנמצאים *כרגע* בספריה שמופיעה בפקודת ה WHERE (ללא פקודת ה WHERE נקבל את רשימת כל קבצי ה SAS בכל ה Libnames) ושומר את התוצאה = רשימת קבצי ה SAS במשתנה מאקרו. אח"כ אפשר להשתמש במשתנה המאקרו הזה בכל מקום שרוצים לדוגמה בפקודת merge ב data step שמופיע מיד לאחר ה SQL.
האם עניתי לשאלה?
הי אריאל / מרים
לקטע ה- SQL יש לצרף גם פקודת separated by על מנת שזה יעבוד.
לא ברור מה הצורך האמיתי בבדיקת קובץ ריק כן / לא
פקודת SET של סאס יודעת להתמודד גם עם קבצים ריקים.
למעשה - אין הבדל האם קבצים ריקים נכללים בפקודת ה- SET או לא
proc sql noprint;
select memname into : names separated by ' '
from dictionary.tables
where libname='WORK'
;
quit;
קצת הסתבכתי עם העברית / אנגלית
מנסה שוב
proc sql noprint;
select memname into : names separated by ' '
from dictionary.tables
where libname='WORK'
;
quit;
תודה רבה אסף על התשובה.
אני אסביר למה מיזוג בSET לא נותן לי את המענה הרצוי אליו אני מכוונת.
כאשר אני ממזגת הרבה קבצים קטנים שכל אחד מהם כולל משתנים רבים ושונים מקובץ לקובץ נוצר לי באמצעות הSET קובץ גדול שמכיל הרבה מאוד משתנים.
הייתי רוצה להגיע למצב שבו הקובץ הסופי יכיל את הקבצים שיש בהם תצפיות ורק את המשתנים שיש בהם מידע. לא בטוחה אם יש דרך לעשות זאת בכלל בסאס, האם יש לך פתרון יצירתי בשביל הבעיה הזו?
שלום @Yul
בפקודת set הוא לוקח אוטומטית את כל השדות בטבלה (למעט אלה שעושים להם drop או לחילופין רק את אלה שעושים להם keep). הוא לא בודק האם יש ערכים או לא.
דרך אגב, פקודת set לא ממזגת בכלל קבצים אלא במקרה הטוב עושה interleaving (שזירה) של קבצים או append לקבצים.
מי שממזג קבצים זו פקודת merge או על ידי שימוש ב PROC SQL.
ההתנהגות של פקודת merge בהקשר של שדות בדיוק כמו שתיארתי למעלה בהקשר של פקודת set.
שימי לב שגם בדוגמה ש @arielbud שלח בהתחלה יש שימוש בפקודת merge לצורך המיזוג.
אם את יודעת מראש שיש שדות בעלי ערכים דומים (נניח מספר טלפון) בכל הטבלאות שאת ממזגת ואת רוצה את הערך הראשון הלא ריק בתור השדה בקובץ הפלט אזי אפשר להשתמש בפונקציה coalesce ב PROC SQL כלומר לעשות את המיזוג עם SQL ולא עם merge משהו כזה:
proc sql;
select coalesce(a.phone, b.phone, c.phone) as phone
from table1 as a, table2 as b, table3 as c
where <join condition>
מקווה שזה עוזר.
אייל
התכוונתי לאיחוד של קבצים ולכן הSET. מכירה את ההבדלים בין MERGE לSET. המינוח שלי בעברית לא היה מדויק.
כאמור אני צריכה לעשות פעולת SET או משהו דומה
שלום @Yul
לידיעה בלבד: אפשר לבצע איחוד קבצים גם עם PROC SQL על ידי האופרטור UNION
דוגמאות לשימוש ב UNION ואופרטורים נוספים אפשר למצוא כאן: https://documentation.sas.com/?docsetId=sqlproc&docsetTarget=n0vo2lglyrnexwn14emi8m0jqvrj.htm&docset...
אייל
שלום @Yul
בנוסף להצעה של אייל נראה לי שהקוד הבא גם יכול לעזור לך.
הוא נראה קצת ארוך אבל הוא רק מורכב מכמה שלבים שכל אחד מהם די פשוט.
חגי
* Generating some sample tables;
data CLASS;
set SASHELP.CLASS;
run;
data CLASS_EMPTY;
set SASHELP.CLASS;
length
Size 8
Teacher $30;
call missing(of _all_);
stop;
run;
data CLASS_HEB(rename=(weight=Miskal height=Gova Name=Shem age=Gil sex=Migdar));
set SASHELP.CLASS;
length
Teacher $30;
call missing(teacher);
run;
*** STEP 1: Appending all tables that are not empty ***;
* Getting all the names of the non empty tables into a macro variable;
* Note - this method will work only if all the tables are SAS tables (datasets);
* The LIBNAME and MEMNAME filters in the WHERE statement need to be
* updated to properly identify all the relevant tables;
proc sql noprint;
select memname into :tables_list separated by " "
from dictionary.tables
where libname="WORK" and memname like 'CLASS%'
and nobs>0;
quit;
%put &tables_list;
* Appending all the non empty tables into one large table;
data ALL_TABLES;
set &tables_list;
run;
*** STEP 2: Finding columns that are all empty ***;
* This method is just one of the possible methods to accomplish this task. Google will offer several more;
* Getting all the columns in the big table we have just created;
proc sql noprint;
create table ALL_TABLES_COLS as
select name
from dictionary.columns
where libname="WORK" and memname = 'ALL_TABLES' ;
quit;
* Creating a SAS program to count the non missing number of values in each column;
* Note - The COUNT function counts only non missing values;
filename sascode temp;
data _null_;
set ALL_TABLES_COLS end=last;
file sascode;
if _n_=1 then do;
put "proc sql noprint;";
put "create table ALL_TABLES_COLS_NMISS as select";
end;
put "count(" name ") as " name @;
if ^last then put ",";
else do;
put /"from ALL_TABLES;";
put "quit;";
end;
run;
* Running the SAS program our SAS program have just created!;
%include sascode;
* Transposing the tables with the number of distinct values in each column to rows;
proc transpose data=ALL_TABLES_COLS_NMISS
out=ALL_TABLES_COLS_NMISS_T(rename=(_name_=Variable_Name col1=Non_Missing_Values));
run;
* Collecting the name of the columns that have at least one non missing value into a macro variable;
proc sql noprint;
select Variable_Name into :columns_list separated by " "
from ALL_TABLES_COLS_NMISS_T
where Non_Missing_Values>0;
quit;
%put &=columns_list;
* Keeping only these columns - dropping the columns that contains all missing values;
data ALL_TABLES;
set ALL_TABLES(keep=&columns_list);
run;
היי, זה לא פותר לי את הבעיה אבל התשובה שלך משלימה לי חלק מהמידע שהיה חסר לי, תודה רבה
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!