美文网首页SAS编程
107:一文搞懂左连接,右连接,全连接等

107:一文搞懂左连接,右连接,全连接等

作者: SASPRO的打工人生活 | 来源:发表于2022-05-04 22:09 被阅读0次

    五一五天眨眼就过去了,还是感叹一句时间过得真快。现在不管是工作日还是放假,每天睁开眼,打开电脑,工作,偷懒,一天就这样过去了。感觉时间不够用,但是又好像在浪费时间。

    今天讲一个轻松的话题,就是SAS中的那些左连接,右连接,乱七八糟的连接,对于初学者来说,不太好理解,我希望初学者看完我今天这篇文章后能有一个更清晰的了解。

    对于工作中的需求,SAS一般能提供好几种解决方式,比如上面讲的连接方式,就可以通过data步中的merge或者是proc sql解决。

    需要注意的是:

    外连接有3种:左连接(left join)、右连接(right join)、全连接(full join)

    与外连接相反的是内连接(inner join)

    用到的数据集:

    test1: 6条观测

    test2:5条观测

    注意test1多了subjid="005"和subjid="006",test2多了subjid="008"

    当他们通过左连接合并的时候

    这里我们以test1作为“主数据集”,test2作为“副数据集”,将“副数据集”拼接到

    “主数据集”上,我们通过 if a来实现。

    注意这里的 in=a 或者是 in = b相当于分别在两个数据集里面创建了临时变量a和b,它们的值好像都是为1。注意,in=a/b你随便取什么名字都可以,你可以 in=main/ss/aaa 任何你喜欢的名字,然后下面对应的ifmain/ss/aaa,只要不要跟数据集里面的变量重名就可以了,要不然会会报错,像这样

    如果你的数据集里面a变量是字符型,会报这个错

    如果你的数据集里面a变量是数值型,会报这个warning,

    所以大家写程序的时候要注意一下,一般越简单越好。

    看下输出:

    看下输出:发现test1里面的观测都保留下来了(绿色),test2里面有相同subjid的观测记录也保留了下来(红色),因为subjid="005"和subjid="006"不在数据集test2里面,所以可以看到var2和age2都是空的。

    不知道是不是还有点抽象,对于初学者可能不太好理解。我们假设有两个俄罗斯方块,a和b,if a就是说a是老大,要向他靠齐(就是说现在有一个人把方块b往左边推,要和a合并,同样颜色的可以合并在一起;不一样的颜色,a的都保留下来,b的就被删除了,所以我们看到test2数据集里面的subjid="008"没出现)

    大家可以在脑海里想象一下这个过程,我希望我讲明白了。

    那么通过proc sql怎么实现这个过程呢?可以通过left join:

    这算是最简单的proc sql写法,但是大家要先熟悉这种写法,注意as不能漏掉,哪里该加逗号,哪里该加分号都要注意,我记得我刚学习proc sql的时候,总是报错,就是犯了上面的错。

    那么右连接呢?其实把if a 换成if b 就可以了,相当于这时候把右边的当成老大了,也就是test2数据集里面的观测都需要保留下来,test1数据集里面的观测只保留有共同subjid的。

    看到subjid="005"和subjid="006"都被删除了。同理,我们在proc sql里面把left join换成right join就可以了,但是同时还要注意,如果我还是如图这样写,会发现subjid="008"怎么不见了,但是这条观测对应的其他变量还是存在的(19,ww)。

    这是因为我们只写成 b.age2,b.var2,然后加上on a.subjid=b.subjid,导致只显示subjid都一样的subjid,其他的subjid则为空,这时候我们可以把a.*换成b.*,同时对a也进行筛选变量,不写成a.*;

    换句话说,只要是你去拼接那个数据集,那个目标数据集就写成xxx.*,相当于保留它的所有记录,同时要对另一个数据集进行筛选,像图片那样a.age1 ,a.var1,如果你写成a.*,b.*,会出现这样的warning:

    或者大家粗暴点,不熟悉右连接,那就都用左连接,然后把test2数据集放到left join前面就可以了

    其实左右连接就像一面镜子,左连接就像另一种形式的右连接,只是把数据集位置换了而已。

    我发现写这些东西就快花了一个多小时,真是醉了,太浪费时间了。

    全连接简单讲讲,全连接就相当于输出两个数据集所有的记录,不管是相同的观测还是不同的观测。

    data 步这样写

    proc sql就有点麻烦了,需要用到coalesce函数,这个函数就是返回参数中第一个不为空的值。

    注意这时候不能简单地写a.*,b.*,要不然又会报subjid已经存在的warning,所以还是得手动筛选一下量(b.age2,b.var2,a.age1,a.var1),同时这个coalesce(a.subjid,b.subjid) as subjid,可以换成你自己取的变量名(比如你想取sub_subjid,coalesce(a.subjid,b.subjid) as sub_subjid,但是你下面的on 还是要保留成subjid)

    如果你只想输出两个数据集共同的部分,不管是只在test1中有记录的观测(subjid="005"和subjid="006")或者只在b中有记录的观测(subjid="008")都被删除.

    data 步这样写:

    看输出就明白了。

    如果要用proc sql实现这种效果,不用写任何join方式(本质上它属于内连接),但是注意这时候使用where筛选,不是用on了,也就是说外连接的3种方式要用on筛选,但是内连接要用where,要不然会报错,这是需要注意的另一个地方。

    左连接(left join)、右连接(right join)、全连接(full join),内连接(inner join)好像只是proc sql的概念,用在data步中好像不合适,同时我感觉data步更好理解,但是存在以下弊端:

    1:用data步merge需要先排序

    2:如果排序变量长度不一致(可以新建排序变量使长度一致),还会报warning,但是proc sql就不会。

    相关文章

      网友评论

        本文标题:107:一文搞懂左连接,右连接,全连接等

        本文链接:https://www.haomeiwen.com/subject/aulgyrtx.html