SAS 中SELECT的两种不同的用法
data 步中的select语句(1)
*genral format;
SELECT(选择表达式);
WHEN(值列表) 语句;
WHEN(值列表) 语句;
...
OTHERWISE 语句;
END;
*
功能及流程:
执行SELECT结构时,先计算出选择表达式和值列表中的所有值,然后把选择表达式值由前
向后与值列表中的值相比,发现相等值则执行对应的语句,然后退出SELECT结构(不再查
看后面的值列表)。如果选择表达式的值不等于任何值列表中的值则执行OTHERWISE对应
的语句,这种情况下没有OTHERWISE语句会出错。
;
类似于Java和C#之类语言中的switch语句
/*sample*/
DATA gebanma;
INPUT month $10.;
datalines;
Mar
Jun
oct
aug
xxx
Jul
Apr
guixiaode
dec
Feb
;
run;
data popSea;
set gebanma;
length season $10.;
SELECT(month);
WHEN('Feb', 'Mar', 'Apr') season= '春天';
WHEN('May', 'Jun', 'Jul') season= '夏天';
WHEN('aug', 'sep', 'oct') season= '秋天';
WHEN('dec', 'nov', 'jan') season= '冬天';
OTHERWISE season= '在武汉';
END;
run;
*效果如下图;
data 步中的select语句(2)
*second format;
SELECT;
WHEN(值列表) 语句;
WHEN(值列表) 语句;
...
OTHERWISE 语句;
END;
*
这种SELECT语句没有选择表达式,而是在每一个WHEN语句指定一个条件(逻辑表达式),
执行第一个满足条件的WHEN后的语句。如果所有条件都不满足则执行OTHERWISE后的语句。
例:
;
data;
input age @@;
put age @;
SELECT;
WHEN(age<=12) put '少年';
WHEN(age<35) put '青年';
OTHERWISE put '中老年';
END;
cards;
10 30 50
;
run;
PROC SQL中的 SELECT CASE WHEN 语句
/*其实这是SQL中的用法 只是功能相似 就放在一起总结一下;
/*SQL 中Case有两种格式*/
/*1 case函数;*/
proc sql outobs=12;
title 'haha';
select Name,Continent,
case Continent
when 'North America' then 'Continental U.S.'
when 'Oceania' then 'Pacific Islands'
else 'None'
end as Region
from sql.unitedstates;
quit;
CASE sex
WHEN '1' THEN '男'
WHEN '2' THEN '女'
ELSE '其他' END
/*2. case搜索函数*/
CASE WHEN sex= '1' THEN '男'
WHEN sex= '2' THEN '女'
ELSE '其他' END
/*两种形式实现的功能相同,简单case函数写法简洁但是与case搜索函数对比 功能较为局限 比如有判断式的加入*/
ps: case函数仅返回第一个符合条件的值,剩余的部分自动被忽略
/*下面的表达式 永远不会返回第二类*/
CASE WHEN col_1 IN ('a','b')THEN '第一类'
WHEN col_1 IN ('a')THEN '第二类'
case的用途
SELECT SUM(population),
CASE country
WHEN '中国' THEN '亚洲'
WHEN '印度' THEN '亚洲'
WHEN '日本' THEN '亚洲'
WHEN '美国' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
ELSE '其他' END
FROM Table_A
GROUP BY CASE country
CASE country
WHEN '中国' THEN '亚洲'
WHEN '印度' THEN '亚洲'
WHEN '日本' THEN '亚洲'
WHEN '美国' THEN '北美洲'
WHEN '加拿大' THEN '北美洲'
ELSE '其他' END;
/*例如判断工资等级*/
SELECT
CASE WHEN salary <=500 THEN '1'
WHEN salart >500 AND salary <=600 THEN '2'
WHEN salart >600 AND salary <=800 THEN '3'
WHEN salart >800 AND salary <=1000 THEN '4'
ELSE NULL END salary_class,
COUNT(*)
FROM Table_A
GROUP BY
CASE WHEN salary <=500 THEN '1'
WHEN salart >500 AND salary <=600 THEN '2'
WHEN salart >600 AND salary <=800 THEN '3'
WHEN salart >800 AND salary <=1000 THEN '4'
ELSE NULL END;
/*
国家(country) 性别(sex) 人口(population)
中国 1 340
中国 2 260
美国 1 45
美国 2 55
加拿大 1 51
加拿大 2 49
英国 1 40
英国 2 60
按照国家和性别进行分组, 得出结果如下
国家 男 女
中国 340 260
美国 45 55
加拿大 51 49
英国 40 60
普通情况下, 用UNION也可以实现用一条语句进行查询。但是那样增加消耗(两个Select部分),
而且SQL语句会比较长。
*/
SELECT country,
sum(CASE WHEN sex='1' THEN population ELSE 0 END),---男性人口
SUM(CASE WHEN sex='2' THEN population ELSE 0 END)---女性人口
FROM Table_A
GROUP BY country;
--在Case函数中Else部分的默认值是NULL, 这点是需要注意的地方。
--一般情况下, 要想把两条数据的Primary key,a和b交换, 需要经过临时存储, 拷贝,
--读回数据的三个过程, 要是使用Case函数的话, 一切都变得简单多了。
/*
p_key col_1 col_2
a 1 张三
b 2 李四
c 3 王五
*/
--假设有如上数据, 需要把主键a和b相互交换。 用Case函数来实现的话, 代码如下
UPDATE Some table
SET p_key = CASE WHEN p_key = 'a'
THEN 'b'
WHEN p_key = 'b'
THEN 'a'
ELSE p_key END
WHERE p_key IN ('a', 'b');
--同样的也可以交换两个Unique key。 需要注意的是, 如果有需要交换主键的情况发生,
--多半是当初对这个表的设计进行得不够到位, 建议检查表的设计是否妥当。
--检查两个表数据是否一致
CASE函数不同于DECODE函数。在CASE函数中,可以使用BETWEEN,LIKE,IS,NULL,IN,EXISTS等等,比如说使用IN,EXISTS,可以进行子查询,从而实现更多功能。
---下面具个例子来说明, 有两个表, tbl_A,tbl_B, 两个表中都有keyCol列。 现在我们对两个表进行比较, tbl_A中的keyCol列的数据如果在tbl_B的keyCol列的数据中可以找到, 返回结果'Matched',如果没有找到, 返回结果'Unmatched'。
---
-- 1. 使用IN语句
SELECT keyCol,
CASE WHEN keyCol IN(SELECT keyCol FROM tbl_B)
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
-- 2. 使用EXISTS语句
SELECT keyCol,
CASE WHEN EXISTS (SELECT *FROM tbl_B
WHERE tbl_A.keyCol=tbl_B.keyCol)
THEN 'Matched'
ELSE 'Unmatched' END Label
FROM tbl_A;
--使用IN和EXISTS的结果是相同的,也可以使用NOT IN 和 NOT EXISTS,但是要考虑到NULL的情况。
在CASE中使用聚合函数
/*
学号(std_id) 课程ID(class_id) 课程名(class_name) 主修flag(main_class_flg)
100 1 经济学 Y
100 2 历史学 N
200 2 历史学 N
200 3 考古学 Y
200 4 计算机 N
300 4 计算机 N
400 5 化学 N
500 6 数学 N
*/
/*有的学生选择了同时修几门课程(100,200)也有的学生只选择了一门课程(300,400,500)。
选修多门课程的学生, 要选择一门课程作为主修, 主修flag里面写入Y。 只选择一门课程的学生,
主修flag为N*/
/*按照下面两个条件对这个表进行查询
只选修一门课程的人, 返回那门课程的ID
选修多门课程的人, 返回所选的主课程ID*/
--条件:只选择一门课程的同学
SELECT std_id,MAX(class_id)AS main_class
FROM Studentclass
GROUP BY std_id
HAVING COUNT(*)=1;
/*
STD_ID MAIN_class
------ ----------
300 4
400 5
500 6
*/
--条件:选择多门课程的学生
SELECT std_id,class_id as main_class
FROM Studentclass
WHERE main_class_flag='Y';
/*STD_ID MAIN_class
------ ----------
100 1
200 3
*/
看使用case函数,能够如何进行简化
SELECT std_id,
CASE WHEN COUTN(*) =1 --只选择一门课程的学生的情况
THEN MAX(class_id)
ELSE MAX(CASE WHEN main_class_flag='Y'
THEN class_id
ELSE NULL END)
END AS main_class
FROM Studentclass
GROUP BY std_id;
/*
STD_ID MAIN_class
------ ----------
100 1
200 3
300 4
400 5
500 6
*/
/*在case中嵌套case,以及在case中使用聚合函数,能够有效的简化sql语句,但是在使用case时需要注意*/
CASE col_1
WHEN 1 THEN 'Right'
WHEN NULL THEN 'Wrong'
END
/*
在上面语句中 when null这一行总是返回unknown,所以永远不会出现wrong的情况
因为 这句等价于when col_1 = NULL 这种用法是错误的,应该选择用when col_1 IS NULL
*/



雷达卡




京公网安备 11010802022788号







