全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
7796 0
2019-12-05

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

*/

  
  

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群