1. 程式人生 > >SAS--SQL過程(基礎版)

SAS--SQL過程(基礎版)

技術 right pan 刪除 圖片 ret || 計算 eat

本文總結SAS中的SQL過程編程技術(基礎版)

Part 1:【select語句綜述】
子句順序(select和from是必要的其他可選):
select
from
where
group by
having
order by

1.建立邏輯庫訪問數據
libname resdat "F:\SAS\ResDat"; /*resdat是一個已經包含本文所用數據的SAS格式的數據集,通過該文件路徑建立邏輯庫來實現數據集訪問*/

2.選擇所有列

proc sql outobs=3; /*outobs=規定輸出的觀測個數*/
select* /*符號*表示選擇所有列*/
from ResDat.dret; /*from+源數據表*/
run;

3.選擇特定列

proc sql outobs=3;
title‘股票代碼和名稱‘; /*title設置表名*/
select stkcd,lstknm /*select+列名*/

from resdat.lstkinfo;
quit;

4.查看表屬性

proc sql;
describe table resdat.lstkinfo;
quit;

5.創建說明列

proc sql outobs=3;
select ‘stock code for‘,lstknm,‘is‘,stkcd
from resdat.lstkinfo;
quit;

技術分享圖片

6.創建新列值

proc sql outobs=3;
title‘trading sum‘;
select stkcd,lstknm,clpr*trdvol format=12.2 /*創建新列值,format用於設定輸出格式*/
from resdat.qttndist;
quit;

proc sql outobs=3;
title ‘trading sum‘;
select stkcd,lstknm,clpr*mcfacpr as adjpr format 8.2, /*為列分配別名*/
(calculated adjpr*trdvol) as trdsum format 12.2 /*使用別名引用一個計算過的列值時須使用calculated關鍵詞*/
from resdat.qttndist;
quit;

技術分享圖片

7.case語句

proc sql outobs=3; /*case可以設定帶有邏輯條件的語句*/
select stkcd,lstknm,lstdt,
case
when exchflg=‘1‘ then ‘上交所‘
when exchflg=‘2‘ then ‘深交所‘
else‘所有交易所‘
end as exchflg /*case最後必須使用end關鍵詞*/
from resdat.lstkinfo
order by lstdt;
quit;

proc sql outobs=3; /*case的另一種表達*/
select stkcd,lstknm,lstdt,
case exchflg
when‘1‘ then ‘上交所‘
when‘2‘ then ‘深交所‘
else‘所有交易所‘
end as newexchflg
from resdat.lstkinfo;
quit;

8.order by語句
proc sql outobs=3;
select stkcd,lstknm,date,clpr*mcfacpr as adjpr format 8.2
from resdat.qttndist
order by adjpr desc; /*按照adjpr降序排列*/
quit;

proc sql outobs=3;
select stkcd,lstknm,date,clpr*mcfacpr as adjpr format 8.2
from resdat.qttndist
order by 4 desc; /*與上式效果同,按照第4列(adjpr)降序排列*/
quit;

9.where語句

proc sql outobs=3;
select lstknm,stkcd from resdat.lstkinfo
where stkcd in(‘000001‘ ‘600651‘ ‘000004‘); /*in算符:找出括號內對應的觀測*/
quit;

技術分享圖片

proc sql outobs=3;
select lstknm,stkcd from resdat.lstkinfo
where lzipsd is missing; /*is missing找出含缺失值的觀測,與is null等價*/
quit;

proc sql;
create table stkinfo1991 as select*from resdat.lstkinfo
where lstdt between‘1jan1991‘d and ‘31dec1991‘d; /*between and 算符:返回1991年的數據*/
quit;

proc sql;
select stkcd,lstknm from resdat.lstkinfo
where lstknm like‘ST%‘; /*like算符:匹配查詢*/
quit;

技術分享圖片

proc sql;
select stkcd,lstknm from resdat.lstkinfo
where lstknm eqt‘ST‘; /*截短算符,與上等價*/
quit;

10.匯總函數

註:匯總函數計算時一般不考慮缺失值

proc sql;
select sum(dividend) format=8.2 as totledv /*sum函數:對dividend變量求和,生成新列totledv*/
from resdat.stk000001;
quit;

技術分享圖片

proc sql;
select count(*)as number /*count函數:匯總所有觀測個數*/
from resdat.lstkinfo;
quit;

proc sql;
select count(distinct stkcd)as count /*存在重復觀測值時的觀測數匯總,所有相同值只匯總一次,忽略缺失值*/
from resdat.qttndist;
quit;

proc sql;
select avg(trdsum) as avgtrdsum format 13.2 /*avg函數:返回非空值的平均值*/
from resdat.idx000001;
quit;

若想考慮進來缺失值,可進行如下操作:

proc sql;
select
case
when trdsum is missing then 0 /*將缺失值置為0*/
else trdsum
end as newtrdsum,
avg(calculated newtrdsum)as avgtrdsum format 13.2
from resdat.idx000001;
quit;

proc sql outobs=3;
title‘2005年股票月收益平均值‘;
select stkcd,avg(monret) as amret from resdat.monret
where‘1jan2005‘d<=date<=‘31dec2005‘d
group by stkcd /*group by: 按stkcd進行分組*/
order by calculated amret desc; /*order by: 按amret進行排序*/
quit;

proc sql; /*列出2005年交易天數不小於240天的股票*/
select stkcd,count(*) as trday from resdat.dret
where ‘1jan2005‘d<=date<=‘31dec2005‘d
group by stkcd
having calculated trday>=240; /*group by+having語句*/
quit;

Part 2:【多表檢索(橫向連接)】

china:

技術分享圖片

usa:

技術分享圖片

1.內連接
proc sql;
select* from resdat.china,resdat.usa /*簡單的內連接,返回where設定的匹配條件的連接行*/
where china.level=usa.level;
quit;
技術分享圖片

proc sql;
select* from resdat.china as a,resdat.usa as b /*使用別名,as可不寫*/
where a.level=b,level;
quit;

proc sql;
select * from resdat.china a inner join resdat.china b /*使用關鍵詞inner join的內連接,這裏相當於自連接*/
on a.level=b.level
order by level;
quit;
技術分享圖片

proc sql outobs=3; /*多表連接*/
select a.stkcd,b.lstknm,c.clpr
from resdat.sampstk a,resdat.lstkinfo b,resdat.qttndist c
where a.stkcd=b.stkcd and b.stkcd=c.stkcd and a.stkcd=c.stkcd;
quit;


2.外連接
proc sql;
select * from resdat.china a left join resdat.usa b /*左外連接,以左邊表為匹配條件,不匹配的在右邊列為空值*/
on a.level=b.level;
quit;

技術分享圖片

proc sql;
select * from resdat.china a right join resdat.usa b /*右外連接:與上相反*/
on a.level=b.level;
quit;
技術分享圖片

proc sql;
select * from resdat.china a full join resdat.usa b /*完全外連接:包括所有不匹配的行(不管左表右表)*/
on a.level=b.level;
quit;

技術分享圖片

/*merge語句:需要對數據預排序*/
data merge;
merge a b;
by code;
run;

Part 3:【子查詢語句】
proc sql;
select*from a
where code eq (select code from b where assistant=‘chen‘); /*單值子查詢*/
quit;

proc sql;
select stkcd,lstknm,lstdt from resdat.lstkinfo
where stkcd in (select stkcd from resdat.sampstk); /*多值子查詢*/
quit;

proc sql;
select stkcd,yrret from resdat.yrret a
where (select stktype from resdat.lstkinfo b /*混合子查詢*/
where a.stkcd=b.stkcd)=‘A‘
and‘1jan2005‘d<=date<=‘31dec2005‘d;

proc sql;
select stkcd,yrret from resdat.yrret a
where exists(select stktype from resdat.lstkinfo b /*exists語句:檢測一組數據存在性,與上式等價*/
where a.stkcd=b.stkcd and stktype=‘A‘)
and‘1jan2005‘d<=date<=‘31dec2005‘d;
quit;

Part 4:【SET算符:合並多個查詢結果(縱向連接)】
a:

技術分享圖片

b:

技術分享圖片

proc sql; /*union:並集,合並兩個查詢結果,返回所有非重復觀測*/
select*from a
union /*若使用unoin all:返回所有觀測*/
select*from b;
quit;
技術分享圖片

proc sql; /*except:差集返回只屬於第一個查詢(a)的觀測*/
select*from a
except
select*from b;
quit;
技術分享圖片

proc sql; /*intersect:交集,返回兩個查詢的公共部分*/
select*from a
intersect
select*from b;
quit;
技術分享圖片

proc sql; /*outer union:直接連接查詢結果(橫向),不合並相同名稱和數據類型的列*/
select*from a
outer union /*若使用outer union corr:合並兩表中相同名稱的列*/
select*from b;
quit;

技術分享圖片

Part 5:【創建與更新表】
1.創建表

1)列定義方式創建表
proc sql;
create table newstkinfo
(
stkcd char(6),
lstknm char(20),
lstdt num informat=date9. /*規定輸入和輸出格式*/
format=date9.
);
quit;
2)從查詢結果創建表
proc sql outobs=3;
create table stkinfo as
select stkcd,lstknm,lstdt
from resdat.lstkinfo;
quit;
3)通過復制創建表
proc sql;
create table stkinfo2 as select*from stkinfo;
quit;
4)/*通過like復制已有表的結構屬性來創建空表*/
proc sql;
create table stkinfo3 like stkinfo2;
5)查看表格屬性
proc sql;
describe table stkinfo3;

2.在表中插入行


1)
proc sql; /*set子句插入觀測,賦值時漏掉某個列,默認缺失*/
insert into stkinfo3
set stkcd=‘000002‘,lstknm=‘萬科A‘,lstdt=‘29jan1991‘d
set stkcd=‘000004‘,lstknm=‘ST國農‘,lstdt=‘14jun1991‘d;
quit;
2)
proc sql; /*values插入觀測,每列都需要賦值,.和‘‘可賦空值*/
insert into stkinfo3
values(‘000001‘,‘s深發展A‘,.)
values(‘000005‘,‘‘,‘10dec1990‘d);
quit;
3)
proc sql; /*在表中插入查詢結果*/
create table stkinfo4 like stkinfo3;
proc sql;
insert into stkinfo4
select* from stkinfo3 where lstdt is not missing;
quit;

3.更新表數據(update)


data invest;
input stkcd$ stknm $ inv;
cards;
000001 深發展 100000
000002 萬科A 50000
000003 方正科技 40000
;
run;
1)同種方式更新
proc sql;
update invest
set inv=inv*1.1; /*把inv提高10%*/
quit;
2)不同方式更新
proc sql;
update invest set inv=inv*1.5 where stkcd=‘000001‘;
update invest set inv=inv*1.4 where stkcd=‘000002‘;
update invest set inv=inv-10000 where stkcd=‘000003‘;
select * from invest;
quit;
3)刪除觀測行
proc sql;
delete from invest where stkcd=‘000003‘;
quit;

4.列修改(alter)


1)add增加列
proc sql;
alter table invest
add total num label=‘總股本‘,ratio num label=‘投資比例‘;
quit;
2)利用update補充新增列的值
proc sql;
update invest set total=400000;
update invest set ratio=inv/total;
quit;
3)modify用於改變列的長度/輸入格式/輸出格式/標簽
proc sql;
alter table invest
modify stkcd char(10) format=$ 10.;
update invest set stkcd=‘res‘||stkcd; /*連接符*/
select*from invest (rename=(stkcd=resstkcd)); /*改變列名*/
quit;
4) 刪除列
proc sql;
alter table invest
drop stknm;
5)刪除表
proc sql;
drop table invest;

附件:本文所用數據集resdat

鏈接:https://pan.baidu.com/s/11Fo7WTkhgmHj1_QggvVsfg 密碼:n4ur

SAS--SQL過程(基礎版)