这是我的代码
libname blood "C:\Users\owner\Desktop\SAS";
data blood.donors1;
input id type $ units;
cards;
2304 o 16
1129 a 48
1129 a 50
1129 a 57
2486 b 63
;
run;
data blood.donors2;
input id code units;
cards;
6488 65 27
1129 63 32
5438 63 39
2304 61 45
1387 64 67
;
run;
proc sort data=blood.donors1 out=blood.donors1;
by id;
run;
proc sort data=blood.donors2
out=blood.donors2;
by id;
run;
data blood.donorsmerge;
merge blood.donors1 (in = indonors1) blood.donors2;
by id;
if indonors1;
run;
以下是结果表donorsmerge
行1129 a 48
完全由1129 63 32
覆盖。但行1129 a 50
和1129 a 57
被部分覆盖。为什么?我看了文档。在我看来,结果数据集应包含我在上图中指出的32
答案 0 :(得分:2)
因为合并并不像它看起来那样完全正常 - 具体来说,它不像SQL连接那样运作。
在幕后,它是如何工作的,对于每个按组,它读取左侧的第一行;然后它找到一个匹配它的行。然后,如果左侧数据集中的组有更多行,则它将转到下一行。如果右边有另一行要匹配,则匹配那两行;否则,它什么都不做。继续,直到按组的最后一行。在写出按组的最后一行但在读取下一个按组的第一行之前,它会清除所有变量。
每个by
组似乎具有code
相同值的原因是来自set
,merge
或update
语句的变量是自动保留。 IE,它们不会丢失(除了在组之间,作为merge
语句的函数)。因此,对于所有三行,code
设置为63 - 第一行设置为63,之后不再更改。
但是,两个数据集上都会显示units
。因此,当第二行被引入左侧,而右侧没有第二行时,它会保留左侧的值。
如果要完全覆盖变量,则需要drop
左侧数据集中的列。如果要覆盖匹配行而不覆盖非匹配行,并且您具有多对一关系(就像在此处一样),则需要在一个数据集或另一个数据集中重命名变量,并使用<{1}}或coalesce
函数(或逻辑)来适当地设置变量。