SQL概念和標準SQL語言
- SQL英文全稱是Structured Query Language,即結構化查詢語言
- SQL是關係數據庫操作的國際標準語言
SQL的功能
- 產生彙總統計表
- 從表和視圖中檢索數據
- 合併表和視圖中的數據
- 建立表、視圖和索引
- 修改、添加、提出表中的數據列
- 更新表中的數據值
SQL過程舉例
Proc sql;/*開始SQL過程*/
create table test as /*創建表*/
select a.comcd, a.lcomchnm, b.stkcd, b.lstknm, a.csrciccd1, count(a.comcd) as n
from resdat.cinfo a left join resdat.lstkinfo b
on a. stkcd=b.stkcd
where estdt>'1jan1985'd
group by a.csrciccd1
order by a.csrciccd1; /*查詢語句*/
quit;/*終止SQL過程*/
一、查詢語句
- SELECT語句是PROC SQL的最主要、最常用的工具。
- 用來識別、檢索和操作表中數據,使用子句可以設定查詢條件。
- 常用子句及其固定順序:
- Select 選擇的變量/列名
- from 來源數據集/表名
- where 選擇條件
- group by 分組標誌(變量)
- having 針對組的選擇條件
- order by 排序標誌(變量)
- 其中只有select和from是必須的,其他子句都是可選的
1. SELECT子句
選擇列
-
特定列:select+列名
-
多個列名用 “,” 分隔;按照語句中順序顯示列
-
所有列:select *
-
刪除重複觀測: select distinct+列名
-
如果有多個列,只刪除所有變量取值都相同的觀測
計算新列值; 爲列分配別名; 指定列屬性;
引用新計算的列:calculated +列名,只能在select和where子句中設定calculated列。
Proc sql;
select name, age, height from resdat.class;
select * from resdat.class;
select distinct age from resdat.class;
Quit;
Proc sql;
select name, weight/height as whratio format=4.2
from resdat.class;
Quit;
Proc sql;
select name, age, weight/height as whratio format 4.2,
(1/calculated whratio) as hwratio format 6.4
from resdat.class;
Quit;
2. WHERE子句
選擇條件:where + 條件表達式
- 比較算符和邏輯算符還有一些等價形式。
- 所有算符前面加一個not算符,可以得到相反的選擇條件。
- 條件較複雜時,可以將表達式用括號括起來,以突出邏輯關係、增強可讀性。
幾個重要條件算符
- in: 符合選項之一; in+(選項1,選項2,…)
- between-and: 選擇一定範圍
- like:部分或全部匹配; %可代替任意數量的字符; _可代替一個字符
proc sql;
select * from resdat.class where age in (12 14 16);
select * from resdat.class where age between 12 and 15;
select * from resdat.class where (sex='F' and weight>100) or (sex='M' and weight<=90);
select * from resdat.class where name like '%h%';
select * from resdat.class where name like '_h%';
quit;
3. GROUP BY和ORDER BY子句
- Group by一般與彙總函數結合使用,彙總函數按照GROUP BY子句進行分組彙總:
- 如果沒有GROUP BY,就默認整個表爲一組;
- 如果沒有彙總函數,則GROUP BY單純分組。
- Order by對結果排序
proc sql;
select name, sex, count(sex) as n, avg(height) as avgh
from resdat.class
group by sex
order by name desc;
quit;
4. HAVING子句
HAVING篩選組數據
- HAVING對組設定條件,進行檢索篩選;
- 在GROUP BY和彙總函數後運行,可以引用匯總函數結果。
與WHERE子句的區別:
- WHERE對觀測設定條件,進行檢索篩選;
- 在GROUP BY和彙總函數前運行,不可以引用匯總函數結果。
proc sql;
select age, avg(height) as avgh
from resdat.class
group by age
having avgh>60;
quit;
SELECT語句綜合練習
選擇resdat.class中,名字首字母不是 B 的學生數據。
- 按年齡分組統計平均體重(avgw)、每組人數(n)
- 輸出平均體重大於100的組,列示年齡、平均體重、每組人數
- 按照年齡倒序排列
proc sql;
select age, avg(weight) as avgw, count(*) as n
from resdat.class
where name not like 'B%'
group by age
having avgw>100
order by age desc;
quit;
二、多表查詢
- FROM後面直接加一個表名,實現從單個表中檢索數據涉及多個表,常使用連接或子查詢。
- 連接查詢: 從多個表中選取數據 數據來自不同的表
- 子查詢: 通過表與表之間的聯繫選取數據 選擇一個表的數據時, 需要參照其他表的信息。
1. JOIN連接——交叉連接
交叉連接(CROSS JOIN)/簡單連接 (,):
最基本的連接,笛卡爾積形式,所有可能組合。
proc sql;
select * from resdat.china cross join resdat.usa;
select * from resdat.china , resdat.usa;
quit;
如果觀測行數很多,這種連接會產生巨大的數據結果,且絕大部分沒有意義,可用其他JOIN連接選擇相應子集。
JOIN連接——內部連接
- 返回兩表中匹配連接條件的行:表a inner join 表b on 連接條件。
- 查詢時經常遇到兩個表有相同列,爲了引用清楚,在列前加表名;
- 爲了書寫和閱讀方便,可在from子句中設定表的別名;
- 關鍵詞inner, as可選;
- 仍然可以使用where、order by等子句。
例:
proc sql;
select * from resdat.china as a inner join resdat.usa as b
on a.level=b.level;
quit;
等價於:
proc sql;
select * from resdat.china a , resdat.usa b
where a.level=b.level;
quit;
JOIN連接——外部連接
- 返回內部連接的行以及部分不匹配連接條件的行;
- 左外部連接(LEFT JOIN):內部連接行+左邊表中不符合匹配條件的行;
- 右外部連接(RIGHT JOIN):內部連接行+右邊表中不符合匹配條件的行;
- 完全外部連接(FULL JOIN):內部連接行+左右兩表中不符合匹配條件的行。
例:
proc sql;
select * from resdat.china a left join resdat.usa b on a.level=b.level;
select * from resdat.china a right join resdat.usa b on a.level=b.level;
select * from resdat.china a full join resdat.usa b on a.level=b.level;
quit;
JOIN連接和MERGE語句比較
-
DATA中的MERGE和SQL過程中的JOIN語句
在很多情況下可以產生相同結果:
- 所有行匹配且無重複值情況:merge=inner join
- 部分行匹配且無重複值情況:merge=full join
-
區別在於:
- 有重複值的情況:merge按照位置順序合併;join根據具體值連接,可以產 生所有組合,並可以選擇其子集;
- JOIN連接之前不需要排序;
- JOIN可以進行不等值連接
-
所以總的來說,JOIN比MERGE更靈活。
JOIN連接綜合練習
按照level相同的原則匹配中美兩隊隊員,分別選擇:
中國隊所有隊員的匹配情況;美國隊所有隊員的匹配情況;
中美兩隊成功匹配的隊員;中美兩隊所有隊員的匹配情況
參考程序:
proc sql;
select * from resdat.china a left join resdat.usa b on a.level=b.level;
select * from resdat.china a right join resdat.usa b on a.level=b.level;
select * from resdat.china a inner join resdat.usa b on a.level=b.level;
select * from resdat.china a full join resdat.usa b on a.level=b.level;
quit;
思考分別如何實現:美國隊內部按照level相同原則匹配?
按照美國隊員比中國隊員level低的原則匹配?
proc sql;
select * from resdat.usa a left join resdat.usa b on a.level=b.level;
select * from resdat.china a left join resdat.usa b on a.level>b.level;
quit;
2. 子查詢
子查詢——簡單子查詢
在一個查詢語句中,用到了另一個查詢的結果
- 簡單子查詢(不相關子查詢):
- 子查詢獨立於外部查詢;
- 子查詢返回的結果要與該查詢外的算符相對應:
- 如果是比較算符如>、=等,子查詢只能返回一個值;
- 如果是條件算符如in、any、all等,子查詢可以返回多個值。
proc sql;
select * from resdat.usa
where level<(select max(level) from resdat.china);
select * from resdat.usa
where level in (select distinct level from resdat.china);
quit;
子查詢——混合子查詢
混合子查詢:子查詢用到外部查詢傳輸進來的值,該子查詢運行後再給外部查詢返回結果;可以返回單值或多值。
- 其實子查詢可以拆分成兩個單獨的查詢,學習創建表之後可以實現
proc sql;
select * from resdat.yrret a
where (select stktype from resdat.lstkinfo b
where a.stkcd=b.stkcd)='A'
and '01jan2005'd<=date<='31dec2005'd;
quit;
合併查詢(SET算符)
-
合併查詢:對兩個完全匹配的查詢結果進行並、差、交運算與JOIN的橫向連接不同,SET算符是豎直的連接。
select 語句1 + SET算符 + select 語句2
-
UNION:產生多個查詢中所有的非重複觀測
-
EXCEPT:產生只屬於第一個查詢、不屬於第二個查詢的觀測
-
INTERSECT:產生兩個查詢共同的觀測
-
OUTER UNION:對多個查詢結果直接連接
三、創建與更新表
- 創建表:CREATE TABLE + 表名
- 列定義方式: CREATE TABLE + 表名+(列名、類型、長度、格式、標籤)
- 從查詢結果創建表: CREATE TABLE + 表名 + AS + SELECT語句
- 新表包括SELECT語句所選擇的列,且保持原來的列屬性
proc sql;
create table class
(code char(6), name char(20),
date num informat=date9. format=data9.);
quit;
proc sql;
create table resdat.class1 as select * from resdat.class;
quit;
利用表過渡,將子查詢拆分成兩個查詢
例:
proc sql;
select * from resdat.usa
where level in (select distinct level from resdat.china);
quit;
拆分:
proc sql;
create table a as select distinct level from resdat.china;
create table b as select * from resdat.usa a join a b
on a.level=b.level;
quit;
使用DATA SET選項:在from語句中的表名後,可以使用DATA SET選項語句。
- 在表中插入行: insert into+表名
- 用SET子句插入行:insert into+表名+ set + 根據列名賦值
- 用VALUES子句插入行: insert into+表名+ VALUES +(對應列的位置賦值)
proc sql;
insert into resdat.class1 set name='Lily', age1=13, sex='F', height=60.5;
insert into resdat.class1 values ('Lucy', 'F', 14, ., 89);
select * from resdat.class1;
quit;
還可以對錶進行以下操作:更新觀測、刪除觀測;增加列、修改列、刪除列;刪除表 等等。
- 在這些功能上,PROC SQL與DATA步相比,沒什麼優勢,因此不做贅述
- PROC SQL還包括視圖功能:
- 對視圖(Views)的各種操作與表(Table)基本相同
- 差別在於:
- 視圖不儲存數據,只是儲存一個查詢語句;
- 在使用該視圖時調用該查詢並展現結果。