SAS(Enterprise Guide)SQL中使用CASE语句时的字符截断问题
问题原因与解决方法
原因分析
在PROC SQL的CASE语句中,SAS会先根据分支里返回值的编译时默认长度确定CASE表达式的结果长度,而非直接采用你在AS text2后指定的LENGTH=1800。
具体来说:
text21中直接调用TRANWRD并指定LENGTH=1800,SAS会直接为该变量分配1800字节的存储空间,因此结果正常。- 但在CASE的
THEN分支中,TRANWRD的替换字符串是通过PUT(t2.Z,8.2)动态拼接生成的,SAS编译时会默认给这个动态拼接的字符串分配较短的临时长度(通常为200字节),导致TRANWRD的结果先被截断到该长度,后续即使指定LENGTH=1800,也无法恢复已丢失的内容。
解决方法
有两种简单有效的处理方式:
方法1:复用已生成的text21变量
既然text21能生成正确长度的结果,直接在CASE语句中引用它即可,还能避免重复计算:
PROC SQL; CREATE TABLE WORK.Area_Z_Added AS SELECT t1.Area, t1.pedArea, t1.Text, /* text21 */ ( tranwrd(t1.Text,'zOffset="0"',compress('zOffset="'||put(t2.Z,8.2)||'"'))) LENGTH=1800 AS text21, /* text2 - 复用text21避免截断 */ (case when t1.type='Area' then text21 else t1.Text end) LENGTH=1800 AS text2, t1.Type, t1.id, t1.x, t1.y, t2.Z FROM WORK.VISSIM_IND t1 LEFT JOIN WORK.AREA_Z t2 ON (t1.Type = t2.Type) AND (t1.Area = t2.Area) ORDER BY t1.id; QUIT;
方法2:强制指定TRANWRD结果的长度
在CASE的THEN分支中,用PUT函数强制将TRANWRD的结果转换为1800字节长度的字符变量,同时将ELSE分支的t1.Text也转为相同长度,确保CASE的两个分支返回值长度一致:
PROC SQL; CREATE TABLE WORK.Area_Z_Added AS SELECT t1.Area, t1.pedArea, t1.Text, /* text21 */ ( tranwrd(t1.Text,'zOffset="0"',compress('zOffset="'||put(t2.Z,8.2)||'"'))) LENGTH=1800 AS text21, /* text2 - 强制指定分支返回值长度 */ (case when t1.type='Area' then PUT(tranwrd(t1.Text,'zOffset="0"',compress('zOffset="'||put(t2.Z,8.2)||'"')), $1800.) else PUT(t1.Text, $1800.) end) AS text2, t1.Type, t1.id, t1.x, t1.y, t2.Z FROM WORK.VISSIM_IND t1 LEFT JOIN WORK.AREA_Z t2 ON (t1.Type = t2.Type) AND (t1.Area = t2.Area) ORDER BY t1.id; QUIT;
内容的提问来源于stack exchange,提问作者Morten
相关产品推荐
相关产品推荐

