我在SAS / SQL中有一个表,如下所示:
输入
Field1 Field2
A B
E F
C D
B C
我想要第三列告诉我可以用Field1和Field2制作的“链”的长度。我将用一个例子来解释。在我们的例子中,我想要:
输出
Field1 Field2 Length
A B 1
B C 2
C D 3
E F 1
这样做会找到“链”并计算其长度。在这个例子中,我们将有2个链:“A-B-C-D”和“E-F”。链首先形成一条带有链的起点的链,在这种情况下是“A-B”。然后,因为Field2中的值是B,它将在Field1中查找值B并将其写入第一行,并使用新的对应值Field2,在本例中为“B-C”。然后它会检查Field1中是否存在值C,如果是这种情况则将其写下来。在我们的例子中,它将是“C-D”。同样,它将检查Field1中是否存在值D.因为它不存在,所以它将使用以下链开始算法,并且会写出没有更多连接的“E-F”。
长度值将给出该对的“深度”。 “A-B”是第一对,“B-C”是第二对链“A-B-C”,“C-D”是第三对链“A-B-C-D”。
我无法找到解决方案,有任何帮助来实现这一目标吗?它不需要完全采用这种形式,任何变通方法都会有很大的帮助。
如果重要的话,对于给定的行,从不是Field1 = Field2的情况。
谢谢!
答案 0 :(得分:0)
在SAS的SQL实现中不可能。
在数据步骤中有很多方法可以做到这一点。如果您了解哈希值,哈希对象可能是最简单的。使用哈希迭代器从哈希中获取第一行,然后获取与field2匹配的任何行;如果没有行匹配field2,请停止查看并让迭代器拉出下一个。
data have;
input Field1 $ Field2 $;
datalines;
A B
E F
C D
B C
;;;;
run;
data want;
if 0 then set have;
declare hash h(dataset:'have', ordered:'a');
h.defineKey('field1');
h.defineData('field1','field2');
h.defineDone();
declare hiter hi('h');
do rc = hi.next() by 0 while (rc=0); *outside iterator - grab the next available row;
seq = 1; *initialize the sequence variable;
output; *output the first row;
do rc_h = h.find(key:field2) by 0 while (rc_h=0); *inside seek - looks for a row (anywhere) that matches field2.;
seq=seq+1; *increment the sequence variable;
output; *output this row;
rc_r = h.remove(); *remove that row from the hash as it has been "used";
rc_h = h.find(key:field2); *look to see if there is another match in this sequence;
end;
rc = hi.next();
end;
stop;
drop rc:;
run;