Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > Macro
Macro Forum d'entraide sur le langage Macro de SAS
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/01/2011, 10h20   #1
Membre habitué
 
Inscription : janvier 2005
Messages : 527
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 527
Points : 134
Points : 134
Par défaut Macrovariable & Call execute - ordre d'execution

Bonjour à tous,

Je pense avoir un problème dans l’ordre d’exécution macro/call execute. A la fin de mon programme, je veux supprimer toutes les tables vides de ma work afin qu’il ne reste que celles à traiter :
- je mets dans la table alltables tous les noms de mes tables
- je parcours la table alltables et j’appelle ma macro killEmptyDS à chaque observation
- ma macro killEmptyDS compte le nombre d’observations de la table passée en entrée et le met dans la macrovariable nobs
- si nobs vaut 0, la table est supprimée

Voici mon code :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
%macro killEmptyDS(dsin1);
 
	proc sql noprint;
		SELECT count(*) INTO: nobs FROM &dsin1;
	quit;
 
	DATA _null_;
		IF &nobs=0 then	call execute(
			'proc datasets lib=work nolist;
	    	delete &dsin1;
	    	quit;
			run;');
	run;
 
%mend killEmptyDS;
 
DATA alltables(keep=memname);
	SET sashelp.vstable;
	WHERE upcase(libname)="WORK";
run;
 
DATA _null_;
	SET alltables;
	call execute('%killEmptyDS('||memname||')');
run;
Le problème est que ma macro variable nobs vaut toujours 16 (c'est-à-dire le nombre d’observations de la première table lue). Donc ma log ressemble à ça :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1    + proc sql noprint;
1    +                           SELECT count(*) INTO: nobs FROM REPORT_DS06;
1    +                                                                            quit;
 
1    +                                                                                        DATA _null_;         IF       16=0
then call execute(             'proc datasets lib=work nolist;            delete &dsin1;            quit;            run;');     run
2    +;
 
 
3    + proc sql noprint;
3    +                           SELECT count(*) INTO: nobs FROM REPORT_DS08;
3    +                                                                            quit;
 
3    +                                                                                        DATA _null_;         IF       16=0
then call execute(             'proc datasets lib=work nolist;            delete &dsin1;            quit;            run;');     run
4    +;
 
 
5    + proc sql noprint;
5    +                           SELECT count(*) INTO: nobs FROM REPORT_DS12;
5    +                                                                            quit;
 
5    +                                                                                        DATA _null_;         IF       16=0
then call execute(             'proc datasets lib=work nolist;            delete &dsin1;            quit;            run;');     run
6    +;

Dans quel ordre faut il executer tout ça pour que nobs prenne la bonne valeur ?

Merci de votre aide.
debdev est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 11h06   #2
Membre Expert
 
Homme
Biostatisticien
Inscription : juin 2009
Messages : 1 143
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Irlande

Informations professionnelles :
Activité : Biostatisticien
Secteur : Industrie Pharmaceutique

Informations forums :
Inscription : juin 2009
Messages : 1 143
Points : 1 760
Points : 1 760
ca ne réponds pas directement à ta question mais pourquoi ne pas éxécuter une proc contents sur toutes les tables de alltables? tu peux alors sélectionner les tables qui n'ont pas d'observations et les stocker dans une nouvelle table, puis éxécuter une proc dataset par exemple pour supprimer ces tables par exemple..
Manoutz est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h02   #3
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
Positionne un %let nobs=0 avant la proc SQL ou un %SYMDEL nobs à la fin de la macro déjà pour voir.

je serai tenté de proposer de prendre une autre voie en considérant que le nombre d'observations est fourni dans la variable NLOBS.

Code :
1
2
3
4
5
6
7
8
9
10
%let qui=work.cnt;
DATA _null_;
dsid=open("&qui");
call symputx('NOBS',attrn(dsid,"NLOBS"));
run;
%put Nobs=&nobs;
 
%IF &nobs=0 %then %do;
proc DELETE DATA=&qui;run;
%end;
Autrement, tu peux tout faire dans une étape DATA _null_ avec fdelete.
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h08   #4
Membre Expert
 
Avatar de MEGAMIND2
 
Homme Brice Beare
Paris
Inscription : janvier 2011
Messages : 956
Détails du profil
Informations personnelles :
Nom : Homme Brice Beare
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Paris

Informations forums :
Inscription : janvier 2011
Messages : 956
Points : 1 366
Points : 1 366
Bonjour,
Visiblement, tu ne peux pas récuperer le nombre d'observation d'une table vide (voir code ci-dessous).
Ton problème en est une autre mais sans résoudre celle là, Tu ne pourras la suppimer

Code :
1
2
3
4
5
6
7
8
DATA MYTABLE;
RUN;

PROC SQL noprint;
		SELECT count(*) INTO: nobs FROM MYTABLE;
QUIT;

%PUT x=&nobs;
MEGAMIND2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h16   #5
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
Salut,
Ton problème est un grand classique maintes fois discuté sur ce forum.

Tu ne peux pas tester nobs par une condition macro car au moment de l'interprétation du code macro, la procédure sql de décompte n'a pas encore été exécutée.

Il faut accéder à nobs d'une autre façon. En utilisant les attributs de la table par exemple :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DATA test;
length u 8;
stop;
run;
 
%macro killEmptyDS(dsin1);
 	DATA _null_;
		IF  nb_obs=0 then call execute(
			"proc datasets lib=work  ;
	    	delete &dsin1;
	    	quit;
			run;");
		SET &dsin1 nobs=nb_obs;
		stop;
	run;
%mend killEmptyDS;
%killEmptyDS(test);
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h23   #6
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
Pas avec nobs mais nlobs stp

Illustration : http://support.sas.com/kb/34/609.html
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h39   #7
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
Citation:
Envoyé par datametric Voir le message
Pas avec nobs mais nlobs stp
Chancun est libre en connaissance de cause d'utiliser l'un ou l'autre.

Citation:
In some cases &NUM may resolve to a non-zero value even if there are 0 observations in the data set
Si la table est issue d'une étape data+set, alors nobs=nlobs.
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 15h50   #8
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
of course. Néanmoins je pense qu'il vaut mieux utiliser NLobs qui fonctionne sans se poser de questions sur la nature des données (logiques, supprimées...). Qu'en penses-tu ?
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 16h34   #9
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
@datametric : ce n'est pas par esprit de contraction mais quand il n'y a pas lieu d'utiliser autre chose j'utilise nobs.

Pour revenir au problème, on peut aussi utiliser la fonction resolve pour remettre dans l'ordre les 2 étapes 1)création de la macro-variable 2) utilisation de la macro-variable.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
 
DATA test;
length u 8;
stop;
run;
%macro killEmptyDS(dsin1);
 
	proc sql noprint;
		SELECT count(*) INTO: nobs FROM &dsin1;
	quit;
 
	DATA _null_;
		IF resolve('&nobs')=0 then	call execute(
			"proc datasets lib=work nolist;
	    	delete &dsin1;
	    	quit;
			run;");
	run;
 
%mend killEmptyDS;
 %killEmptyDS(test);
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 16h40   #10
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
Je pense qu'il vaudrait mieux éviter cette proc SQL qui force la lecture de la table alors que notre solution avec nobs ou nlobs est beaucoup plus efficace.

Autre point, il me semble que si tu initialisais nobs=0 avant la proc SQL et si la table ne pouvait pas renvoyer de valeur dans le cas où elle était vide, alors nobs resterait à zéro et le test suivant fonctionnerait.
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 16h43   #11
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Bonjour,

Manoutz à proposer une bonne solution.

Cordialement
Salah
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 17h06   #12
Membre confirmé
 
Inscription : janvier 2010
Messages : 185
Détails du profil
Informations forums :
Inscription : janvier 2010
Messages : 185
Points : 250
Points : 250
Citation:
datametric :
Je pense qu'il vaudrait mieux éviter cette proc SQL qui force la lecture de la table alors que notre solution avec nobs ou nlobs est beaucoup plus efficace.
Oui effectivement ne jamais lire une table quand ce n'est pas nécessaire.
Je voulais juste donner un exemple d'utilisation de la fonction resolve qui permet ici de faire se rejoindre l'intention du développeur et le code "call-exécuté".

@bahraoui:

effectivement la solution de Manoutz est bonne. On peut externaliser la sélection des tables vides et lancer le call execute de destruction (exempt de test sur le nombre d'obs) => plus de souci de désynchro.
sasadm est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 17h22   #13
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
Je vous propose la solution ci-dessous:
proc contents pour déterminer les tables à 0 observations
proc sql pour créer une liste avec le nom des tables à 0 obs
proc datasets pour supprimer les tables sélectionnées avant
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
DATA t1;
input a;
cards;
;
run;
DATA t2;
input a;
cards;
;
run;
DATA t3;
input a;
cards;
1
;
run;
proc contents DATA=_all_ out=res(keep=MEMNAME NOBS) noprint;
run;
proc sql;
SELECT memname INTO :list separated BY ' '
FROM res
WHERE nobs=0;
quit;
%put &list;
proc datasets lib=work;
DELETE &list;
quit;
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 17h30   #14
Expert Confirmé
 
Avatar de olivier.decourt
 
Homme Olivier Decourt
Formateur en informatique
Inscription : avril 2008
Messages : 1 467
Détails du profil
Informations personnelles :
Nom : Homme Olivier Decourt
Âge : 34
Localisation : France

Informations professionnelles :
Activité : Formateur en informatique
Secteur : Conseil

Informations forums :
Inscription : avril 2008
Messages : 1 467
Points : 2 823
Points : 2 823
Je renchéris sur l'excellent programme de Bahraoui pour proposer une variante qui peut chercher les tables vides dans plusieurs bibliothèques, voire toutes, avec la vue système DICTIONARY.TABLES plutôt qu'une procédure CONTENTS.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
DATA t1;
input a;
cards;
;
run;
DATA t2;
input a;
cards;
;
run;
DATA t3;
input a;
cards;
1
;
run;
proc sql NOPRINT ;
SELECT memname INTO :list separated BY ' '
FROM dictionary.TABLES
WHERE nobs=0 AND UPCASE(libname) IN ("WORK","SASUSER") ;
quit;
%put &list;
proc datasets lib=work  NOLIST ;
DELETE &list;
quit;
Olivier
olivier.decourt est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 17h31   #15
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
c'est encore mieux
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2011, 17h45   #16
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
la vue système est une ... vue donc je ne suis pas certain qu'en temps d'exécution ce soit mieux. L'un de vous deux peut faire un test ?
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2011, 11h07   #17
Membre Expert
 
Inscription : mars 2005
Messages : 1 010
Détails du profil
Informations forums :
Inscription : mars 2005
Messages : 1 010
Points : 1 258
Points : 1 258
Envoyer un message via Yahoo à bahraoui
J'ai fait plusieurs lancements du code ci-dessous la contents est toujours plus rapide.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
 proc contents DATA=_all_ out=res(keep=MEMNAME NOBS);
92   run;
 
NOTE: La TABLE WORK.RES a 6 observations et 2 VARIABLES.
NOTE: La procédure CONTENTS a utilisé (Durée totale du processus) :
      temps réel                   0.12 secondes
      temps processeur   0.03 secondes
 
3   proc sql NOPRINT ;
54   SELECT memname INTO :list separated BY ' '
55   FROM dictionary.TABLES
56   WHERE nobs=0 AND UPCASE(libname) IN ("WORK") ;
57   quit;
NOTE: La procédure SQL a utilisé (Durée totale du processus) :
      temps réel                   5.54 secondes
      temps processeur   0.51 secondes
Se baser sur la proc contents est plus rapide que sur la vue système.
__________________
Consultez les FAQs et les anciens postes avant de poser vos questions. Merci
bahraoui est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2011, 11h18   #18
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2011, 07h24   #19
Membre habitué
 
Inscription : janvier 2005
Messages : 527
Détails du profil
Informations forums :
Inscription : janvier 2005
Messages : 527
Points : 134
Points : 134
Waou !
Je n'ai pas pu revenir sur le forum depuis mon message initial.
Alors, je vous remercie tous pour votre aide. J'avoue que je viens seulement de lire vos messages à l'instant, je n'ai rien testé encore, mais je ne doute pas une seconde que ça fonctionne.
Un grand merci à tous.
Bonne journée
debdev est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h59.


 
 
 
 
Partenaires

Hébergement Web