SAS中用PROC SQL管理数据
(2010-04-13 11:22:34)
标签:
namesassqlfrom张聪杂谈 |
分类: 06.统计软件 |
用PROC SQL管理数据
SAS系统首先是一个数据管理系统,因此它除了可以用SAS语言程序管理SAS数据库、数据集外,还提供了其它大型数据库管理系统(如Oracle、Sybase)通用的SQL语言功能。在SAS 系统中SQL语言实现在SQL过程中。SAS的SQL过程可以从一个或多个表中查询信息,生成表,向表中插入行,更新表的内容,对表进行纵向合并、横向连接等等。另外,PROC SQL还可以直接连接外部数据库,我们已经在2.1.3作了介绍。SQL语言可以实现极其复杂的数据管理功能,在这里我们只对它的查询功能作简单介绍,感兴趣的读者可以自己阅读一些数据库管理方面的书籍。
用PROC SQL作查询的最简单的用法如下:
PROC SQL;
SELECT 第一项,第二项,…,第n项
FROM 数据集
WHERE 观测选择条件;
RUN;
其中SELECT是一个语句,FROM和WHERE叫做子句,注意语句是在最后结尾的,中间没有分号。SELECT子句中指定的各项一般为变量名,中间用逗号分隔(注意不是用空格分隔)。FROM 子句指定要从哪个数据集查询。WHERE子句指定选择观测的条件。所以,SELECT语句可以很方便地从一个表查询一个子集,并可以自动输出到输出窗口而不需再使用PROC PRINT。例如,下面的程序显示语文成绩在100分以上(包含)的学生的姓名和数学成绩:
proc sql;
select name, math
from c9501
where chinese>=100;
run;
结果显示
NAME MATH
--------------------
张红艺 89
张聪 98
刘颍 80
在SELECT语句中还可以加入ORDER BY子句,可以为查询结果排序。比如,下程序
proc sql;
select name, math
from c9501
where chinese>=100
order by math desc;
run;
结果为
NAME MATH
--------------------
张聪 98
张红艺 89
刘颍 80
SELECT的强大查询功能还表现在它可以从几个表联合查询。比如,考虑2.3.7中的C9501X 和C9501Y,我们要从这两个数据集查询与从C9501一个数据集同样的结果,可以用此程序:
proc sql;
select c9501x.name, math
from c9501x, c9501y
where c9501x.name=c9501y.name
and chinese>=100
order by math desc;
run;
其中连接两个数据集的办法是在WHERE子句指定C9501X.NAME=C9501Y.NAME这样的连接条件。在SELECT中指定变量时如果有两个数据集中共有的变量要用C9501X.NAME这样的带有表名(数据集名)的形式。
连接的两个表有时是同一个表。比如,我们有几个学生的姓名和生日,希望找出那些有相同生日的人。可以用如下的SQL过程:
title '找出生日相同的人';
data class;
input name $ 1-8 birth yymmdd10.;
format birth yymmdd10.;
label name='姓名' birth='生日';
cards;
李明 78-6-1
王思明 78-5-19
张聪 78-6-1
刘颖 78-10-18
张红艺 78-5-19
;
proc sql;
select name, birth
from class a
where birth in select birth
from class b
where b.name ^= a.name
order by a.birth;
run;
结果如下:
找出生日相同的人
姓名
--------------------
王思明
张红艺
张聪
李明
如果我们还希望把查询的结果存入一个数据集,可以在上面的第一个SELECT语句前面加上CREATE TABLE 表名 AS:
proc sql;
CREATE TABLE bsame AS
select name, birth
from class a
…………………
run;
proc print data=bsame label;
id name;
by birth;
run;
结果如下:
找出生日相同的人 22
生日=1978-05-19
姓名
王思明
张红艺
生日=1978-06-01
姓名
张聪
李明
如果不用SQL过程想得到同样的结果,可以使用如下数据步和过程步:
proc freq data=class noprint;
tables birth / out=bfreq;
run;
proc sort data=class;
by birth;
proc sort data=bfreq;
by birth;
data bsame;
merge class bfreq;
by birth;
if count>1;
run;
proc print data=bsame label noobs;
var name;
by birth;
run;