基于多列的SAS表左连接问题:单列匹配多列遇数据类型错误
SAS左连接:单列匹配多列的实现方案
问题背景
需要将表IPDTE.ipdte103pt3(表A)与GBD.GBD_expand_test1(表B)做左连接,用表A的ICD9CM_1_v3列匹配表B的30个cause_code_uni_1到cause_code_uni_30列。习惯用R,初次用SAS实现时遇到两个问题:
- 手动写多个OR的匹配条件过于繁琐
- 执行时出现数据类型不匹配报错:
ERROR: Expression using = has components that are of different data types.
第一步:解决数据类型不匹配问题
报错原因是匹配的两个变量类型不一致(比如一个是字符型,一个是数值型),需要先统一类型:
- 如果表A的
ICD9CM_1_v3是字符型,表B的cause_code_uni_*是数值型:用put函数把数值转成字符,示例:
proc sql; create table ipdte_gbd as select A.*, B.* from IPDTE.ipdte103pt3 as A left join GBD.GBD_expand_test1 as B on A.ICD9CM_1_v3 = put(B.cause_code_uni_1, $10.) /* $10.根据实际字符长度调整 */ or A.ICD9CM_1_v3 = put(B.cause_code_uni_2, $10.) or A.ICD9CM_1_v3 = put(B.cause_code_uni_3, $10.); quit;
- 如果表A的
ICD9CM_1_v3是数值型,表B的cause_code_uni_*是字符型:用input函数把字符转成数值,示例:
proc sql; create table ipdte_gbd as select A.*, B.* from IPDTE.ipdte103pt3 as A left join GBD.GBD_expand_test1 as B on input(A.ICD9CM_1_v3, best.) = B.cause_code_uni_1 or input(A.ICD9CM_1_v3, best.) = B.cause_code_uni_2 or input(A.ICD9CM_1_v3, best.) = B.cause_code_uni_3; quit;
可以先用proc contents查看变量类型:
proc contents data=IPDTE.ipdte103pt3; run; proc contents data=GBD.GBD_expand_test1; run;
第二步:用宏简化30个匹配条件
手动写30个OR太麻烦,用SAS宏循环自动生成匹配条件:
%macro join_multiple_cols; proc sql; create table ipdte_gbd as select A.*, B.* from IPDTE.ipdte103pt3 as A left join GBD.GBD_expand_test1 as B on %do i=1 %to 30; A.ICD9CM_1_v3 = put(B.cause_code_uni_&i., $10.) /* 根据实际类型调整转换方式 */ %if &i. ne 30 %then or; /* 最后一个条件不加OR */ %end; ; quit; %mend; %join_multiple_cols; /* 调用宏 */
如果是数值转字符的情况,把put换成input即可,比如:
input(A.ICD9CM_1_v3, best.) = B.cause_code_uni_&i.
注意事项
- 转换格式(比如
$10.、best.)要根据实际变量的长度/精度调整,避免截断或转换错误 - 左连接可能会产生重复行:如果表B中有多个列匹配到表A的同一行,结果会生成多条记录,后续可以根据需求去重
内容的提问来源于stack exchange,提问作者Luz
相关产品推荐
相关产品推荐

