SAS:如何在 proc sql WHERE 语句中迭代数据集元素?
SAS : How to iterate a dataset elements within the proc sql WHERE statement?
我需要使用 proc sql
创建多个 table
proc sql;
/* first city */
create table London as
select * from connection to myDatabase
(select * from mainTable
where city = 'London');
/* second city */
create table Beijing as
select * from connection to myDatabase
(select * from mainTable
where city = 'Beijing');
/* . . the same thing for other cities */
quit;
这些城市的名称在 sas table myCities
中
如何将 data
步骤嵌入 proc sql
以遍历所有城市?
- 您需要将 proc sql 代码放入 SAS 宏中。
- 为 City 创建一个宏变量(在我的示例中,我将宏变量命名为 "City")。
从数据步程序执行宏。由于 Datastep 程序针对每个观察处理一个,因此无需创建复杂的逻辑来迭代。
data mycities;
infile datalines dsd;
input macrocity $ 32.;
datalines;
London
Beijing
Buenos_Aires
;
run;
%macro createtablecity(city=);
proc sql;
/* all cities */
create table &city. as
select * from connection to myDatabase
(select * from mainTable
where city = "&city.");
quit;
%mend;
data _null_;
set mycities;
city = macrocity;
call execute('%createtablecity('||city||')');
run;
proc sql noprint;
select quote(city_varname) into :cities separated by ',' from myCities;
quit;
*上面的这一步创建了一个列表作为宏变量,以与下面的 in() 运算符一起使用。编辑:根据 Joe 的评论,添加了 quote() 函数,以便每个城市都将进入引号内的宏变量列表,以供下面的 in() 运算符正确引用。
create table all_cities as
select * from connection to myDatabase
(select * from mainTable
where city in (&cities));
*这一步只是您在问题中提供的步骤,稍作修改以将 in() 与上面定义的宏变量列表一起使用。
一个相对简单的解决方案是完全在一个数据步骤中完成。假设您可以通过 libname 连接(如果您可以通过 connect to
连接,您可能可以),假设 libname 是 mydb
。第一部分使用与 Max Power 类似的结构:
proc sql noprint;
select city_varname
into :citylist separated by ' '
from myCities;
select cats('%when(var=',city_varname,')')
into :whenlist separated by ' '
from myCities;
quit;
%macro when(var=);
when "&var." output &var.;
%mend when;
data &citylist.;
set mydb.mainTable;
select(city);
&whenlist.;
otherwise;
end;
run;
如果您正在使用 mainTable 中的大部分数据,这可能不会比在数据库端执行它慢多少,因为无论如何您都在移动所有数据 - 并且可能会更快,因为你只访问了一次数据库。
更好的方法是将它拉到一个 table(如 Max 所示),但如果您确实需要创建多个 table,这是一种合理的方法。
确实与这里的其他解决方案类似,也许更简单一些...拉出一个不同的城市列表,放入宏中,运行 SQL 在 do 循环中查询。
Proc sql noprint;
Select distinct city, count(city) as c
Into :n1-:n999, :c
From connection to mydb
(Select *
From mainTable)
;
Quit;
%macro createTables;
%do a=1 %to &c;
Proc sql;
Create table &&n&a as
Select *
From connection to myDb
(Select *
From mainTable
Where city="&&n&a")
;
Quit;
%end;
%mend createTables;
%createTables;
我需要使用 proc sql
proc sql;
/* first city */
create table London as
select * from connection to myDatabase
(select * from mainTable
where city = 'London');
/* second city */
create table Beijing as
select * from connection to myDatabase
(select * from mainTable
where city = 'Beijing');
/* . . the same thing for other cities */
quit;
这些城市的名称在 sas table myCities
如何将 data
步骤嵌入 proc sql
以遍历所有城市?
- 您需要将 proc sql 代码放入 SAS 宏中。
- 为 City 创建一个宏变量(在我的示例中,我将宏变量命名为 "City")。
从数据步程序执行宏。由于 Datastep 程序针对每个观察处理一个,因此无需创建复杂的逻辑来迭代。
data mycities; infile datalines dsd; input macrocity $ 32.; datalines; London Beijing Buenos_Aires ; run; %macro createtablecity(city=); proc sql; /* all cities */ create table &city. as select * from connection to myDatabase (select * from mainTable where city = "&city."); quit; %mend; data _null_; set mycities; city = macrocity; call execute('%createtablecity('||city||')'); run;
proc sql noprint;
select quote(city_varname) into :cities separated by ',' from myCities;
quit;
*上面的这一步创建了一个列表作为宏变量,以与下面的 in() 运算符一起使用。编辑:根据 Joe 的评论,添加了 quote() 函数,以便每个城市都将进入引号内的宏变量列表,以供下面的 in() 运算符正确引用。
create table all_cities as
select * from connection to myDatabase
(select * from mainTable
where city in (&cities));
*这一步只是您在问题中提供的步骤,稍作修改以将 in() 与上面定义的宏变量列表一起使用。
一个相对简单的解决方案是完全在一个数据步骤中完成。假设您可以通过 libname 连接(如果您可以通过 connect to
连接,您可能可以),假设 libname 是 mydb
。第一部分使用与 Max Power 类似的结构:
proc sql noprint;
select city_varname
into :citylist separated by ' '
from myCities;
select cats('%when(var=',city_varname,')')
into :whenlist separated by ' '
from myCities;
quit;
%macro when(var=);
when "&var." output &var.;
%mend when;
data &citylist.;
set mydb.mainTable;
select(city);
&whenlist.;
otherwise;
end;
run;
如果您正在使用 mainTable 中的大部分数据,这可能不会比在数据库端执行它慢多少,因为无论如何您都在移动所有数据 - 并且可能会更快,因为你只访问了一次数据库。
更好的方法是将它拉到一个 table(如 Max 所示),但如果您确实需要创建多个 table,这是一种合理的方法。
确实与这里的其他解决方案类似,也许更简单一些...拉出一个不同的城市列表,放入宏中,运行 SQL 在 do 循环中查询。
Proc sql noprint;
Select distinct city, count(city) as c
Into :n1-:n999, :c
From connection to mydb
(Select *
From mainTable)
;
Quit;
%macro createTables;
%do a=1 %to &c;
Proc sql;
Create table &&n&a as
Select *
From connection to myDb
(Select *
From mainTable
Where city="&&n&a")
;
Quit;
%end;
%mend createTables;
%createTables;