1
基本结构
代码语言:javascript复制proc sql noprint;/*来申明Proc sql 过程步*/
create table report_ as /*创建一个表*/
select distinct * /*选出需要的变量或者字段*/
from ; /*变量或者字段来自哪一个表*/
quit;
*distinct 去掉重复观测的选项;
代码语言:javascript复制proc sql noprint;
create table report_ as
select distinct *
from as a
left join as b
on a. =b.
and a. =b.
group by
order by
;
quit;
见上图:第一部分是一个简单的查询结构,第二部分小编设置快捷键(输入Sql后)自动弹出的结构(一个左连接的基本结构),快捷键的设置见小编历史推送(点击此处自动跳转:快捷键设置)。基本结构是这样的,基本就是这样的。还是用例子个程序来介绍在SAS里面的用途。
2
SQL应用的几个例子
在临床试验中,经常会出一些汇总的报告,比如各中心入组人数,各中心完成试验人数,各中心退出人数,脱了人数...(分中心小结的report),这个时候其实是可以用SQL语句来快速汇总出这些结果。
看上面的一段Sql代码:得到的结果是这样的
代码语言:javascript复制proc sql noprint;
create table Temp1 as
select distinct siteid,count(*) as num label="完成试验人数"
from raw.ds where dscompyn='1'
group by siteid
order by siteid;
create table Temp2 as
select "总计" as siteid,count(*) as num
from raw.ds where dscompyn='1';
create table Temp as
select * from Temp1
union all
select * from Temp2;
quit;
这段代码其实很基础:不过用到了SQL 中好几个知识点,其实好像也没神马知识点,也就是一个筛选(where语句),一个计算行数(count(*)),一个分组(group by),一个排序(order by),一个数据集的追加(union all)然后没了,这些都是很基础的用法。当然这儿不一定非要用SQL,也可以用其他的过程步(proc mean /proc freq等)
来见一下:proc freq的写法(不过,小编对freq过程步做汇总不是很熟,总计那个值不知道啥参数可以出,各位大神如果知道告诉我一下,
最近变懒了,不想百度了。)
代码语言:javascript复制proc freq data=Raw.DS noprint;
where dscompyn='1';
table siteid/chisq nopercent norow nocol out=aaa1(drop=PERCENT);
run;
在来见一下:proc mean的写法:
代码语言:javascript复制proc means data = raw.ds noprint;
where dscompyn='1';
class Siteid;
output out=temp3(drop=_FREQ_ ) n = cnt ;
run;
我突然发现...我好像歪楼了~
代码越写越少,效果却真的相差无几,其实我想说SQL的优点的...好吧,这样一对比,SQL好像没有优点....其实SQL在这儿也很好用,虽然看着代码长一点,但是我还是很喜欢这样用的。freq过程步与means过程步同样很好用,小编以前都是用freq过程步去算分中心小结的report。我还是建议,方法知道的越多越好...毕竟也是长见识,兴许以后啥时候能通过曾经的几种方法给你写程序的灵感呢。所以啊,没事的时候还是多看书,多思考...
在临床试验数据清洗的时候,我们经常需要用到筛选语句,那么筛选语句改怎么写?where可以出现的位置有哪些呢?
需求1:找出年龄最大的受试者?奥,好像一般没有这样的需求,那就找出年龄大于50岁的受试者?(年龄通用的计算方式:AGE=INT((知情同意日期-出生日期)/365.25));
代码语言:javascript复制proc sql noprint;
create table need1(where=(age=max_age)) as
select distinct usubjid,int((input(rficdtc,yymmdd10.)-input(brthdtc,yymmdd10.))/365.25) as age,
Max(int((input(rficdtc,yymmdd10.)-input(brthdtc,yymmdd10.))/365.25)) as Max_age
from Raw.dm
;
quit;
小编想来想去,还是把怎么求最大年龄写在这里。在这里,有没有发现小编将where 写到need1后面,而不是raw.dm后面。其实这个就是小编想说的,where语句的位置。有时候在不同地方效果不是一样的。
代码语言:javascript复制proc sql noprint;
create table need2 as
select distinct usubjid,int((input(rficdtc,yymmdd10.)-input(brthdtc,yymmdd10.))/365.25) as age,
Max(int((input(rficdtc,yymmdd10.)-input(brthdtc,yymmdd10.))/365.25)) as Max_age
from Raw.dm where age=max_age;
quit;
这段代码,小编是写在raw.dm下,但是这样写是回报错的喔。看一看Log说了些神马。
这个ERROR说age,Max_age这些列没有找到?不是明明select的时候创建了这些变量了么?这个问题的答案其实很简单,此处的where语句针对的raw.dm这个数据集进行的筛选,而need2后面的where是针对need2数据集进行的筛选。所以啊...where的位置不同,效果也会不同的~还是贴一下正确程序运行的效果。
在实际的工作中,经常会有一种筛选(子查询)的运用,我有一个清单的受试者,我想要提取清单中受试者的信息,随便举一例:请找出发生不良事件受试者研究总结页填写的信息?
哎呀,小编好像是造题小能手,信手拈来就是题
先来看看代码怎么写:
代码语言:javascript复制proc sql noprint;
create table temp4 as
select distinct *
from raw.ds where usubjid in (select usubjid from raw.ae where aeyn='1')
;
quit;
看,代码是不是很少。这里就用到了子查询,看from 那一行中的where语句,查询套查询,其实还能无效套吧。这里小编要说的就是一个子查询功能。效果就不看了~肯定不会有error,我就是那么一个有自信的人!
不管是在那个行业,只要用SAS一般都会对数据结构进行处理吧,多表的合并等操作,各种连接(内连接,外连接,左连接,右连接....等等),在data步中有mege和set,在sql步中就更多了,本篇前面就提到union all,还有join等等。
代码语言:javascript复制proc sql UNDO_POLICY=NONE;
create table report_ as
select distinct a.siteid format=$200.,a.Count label="筛选人数" ,d.Count as Count1 label="筛选失败人数",
e.Count as Count2 label="随机人数" ,b.COUNT as COUNT3 label="完成研究人数",c.COUNT as COUNT4 label="提前中止研究人数"
from aaa2 as a
left join aaa1 as b
on a.siteid =b.siteid
left join aaa3 as c
on a.siteid =c.siteid
left join aaa4 as d
on a.siteid =d.siteid
left join aaa5 as e
on a.siteid =e.siteid
;
quit;
简单几个例子,小编很早的时候SAS技术不怎么好的时候就特别喜欢用freq,和left ,还有means,还有append合并起来用,算一个分中心小结
是不是觉得小编一个简单需求玩出花样的写,就是那么喜欢炫耀自己知识点多~实则不然,那是因为小编技术很low,各种没学好,一个简单的需求,其实几行就搞定了,还搞这么多。。所以啊,技术好的人代码都很精炼,找不出挑剔,这也就是学习多种方法去实现自己的程序的一个好处,用最优的方法,代码拿出去给人看,肯定会有好评的。这也是我不断追求和探索的一个学习方式。要说啥来着,我都忘记了。
在插入一段代码:小编曾经写了一个Output query的Macro,其核心就是利用的Sql中的full join。(点击此处跳转到那个Macro:Macro-Output Query(Edit Check Macro))
代码语言:javascript复制proc sql UNDO_POLICY=NONE;/*where语句核查情况*/
create table Chk as
select distinct &&ChkMainDATA&i...&SubjidKey.,&&ChkMainDATA&i...&VisitKey. ,&&ChkMainDATA&i...&PageKey. ,
"&&ChkDvpCode&i." as DVP_CODE length=200,"&&ChkDesc&i." as DECL length=2000,&&ChkQUERY&i. as Query length=2000
from &&ChkMainDATA&i.
%if %length(&CDataSet1.)^=0 %then %do;
full join &CDataSet1. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet1..&SubjidKey.
%end;
%if %length(&CDataSet2.)^=0 %then %do;
full join &CDataSet2. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet2..&SubjidKey.
%end;
%if %length(&CDataSet3.)^=0 %then %do;
full join &CDataSet3. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet3..&SubjidKey.
%end;
%if %length(&CDataSet4.)^=0 %then %do;
full join &CDataSet4. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet4..&SubjidKey.
%end;
%if %length(&CDataSet5.)^=0 %then %do;
full join &CDataSet5. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet5..&SubjidKey.
%end;
%if %length(&CDataSet6.)^=0 %then %do;
full join &CDataSet6. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet6..&SubjidKey.
%end;
where &&ChkCondt&i.
;
quit;
接着继续:关于SQL中的多表合并小编也曾经写过一篇推送,利用有merge的用法以及对于SQL的用法:(点击此处跳转:SAS Join(Proc sql) PK Merge(Data Step))
关于SQL的用法小编还是要在推荐一个朋友总结的文章点击此处
:[1]SAS— proc sql 语句 [2]SAS sql
关于SQL宏变量的定义,以及数据字典使用,小编打算放到以后写有关宏基础的推送里面写。
Sql还有啥用法呢,好像真的还有很多的,不过小编好像突然失忆了,想不起来了。所以啊,就为大家在推荐一本纯讲SAS中SQL用法的一本书:网盘链接以及为你准备好了:https://pan.baidu.com/s/1c2TXJhQ
名字是这个~