Tartaglia的答案相当接近,但它可能更容易一步完成。
data x1 x2;
merge x(in=x) a(in=found keep=id) b(in=found keep=id) c(in=found keep=id);
by id;
if x and found then output x1;
else if x then output x2;
run;
确保“发现”和“X”是任何原始数据集不变量,否则使用别的 唯一复杂的因素是,如果你想从A,B,C比ID其他一些变量;如果你这样做,那么你需要弄清楚如何确保你得到正确的变量,如果你有一个多重匹配场景。还需要整理所有四个表格(可能会很慢)。
另一个SAS解决方案:散列表。这是而不是需要排序你的数据集。如果您的数据集尚未排序,这可能会更快。但是,它确实需要足够的内存来将所有表a,b和c存储在内存中,这可能会受到这些数据集大小的限制;当a,b,c相对于x较小时,而不是当它们的尺寸相似时更好。可以使用defineData来操纵这些数据,以便从a/b/c中生成数据,而不仅仅是返回代码,但是如果在a,b,c中的两个中找到想要执行的操作,三个全部)。
data abc/view=abc;
set a b c;
keep id;
run;
data x1 x2;
if _n_ = 1 then do;
declare hash abc(dataset:"abc");
abc.defineKey("id");
abc.defineDone();
call missing(id);
end;
set x;
rc = abc.find();
if rc=0 then output x1;
else output x2;
run;
要做到这一点在Oracle中,我想我会做的是做一些更接近塔尔塔利亚的解决方案的方式 - 创建三个“匹配”的表,然后工会它们(除去在工会重复),然后创建x2作为x减x1表。
create table x1 as
select x.* from x,a where x.id=a.id
union
select x.* from x,b where x.id=b.id
union
select x.* from x,c where x.id=c.id
;
create table x2 as
select * from x except select * from x1;
我测试过这些了使用SAS(包括SQL解决方案,Oracle可能会好一点的,但是:IE浏览器(Oracle是否准确以外,则这个作品在PROC SQL在SAS,不知道)应该是类似的顺序 - 但如果你的oracle服务器比你的sas服务器更快,那可能会改变一些东西)。
使用数据集'x'与5e7记录和三个数据集'a''b''c'进行公平重叠(大概25%左右的记录在2个或更多数据集中,84%在一个或更多)和每个1.5e7和3e7记录之间(具体来说,其中一个具有所有奇数,一个具有3的倍数,并且一个具有4的倍数),SQL解决方案花费了5分钟来处理,而排序合并解决方案需要大约2.5分钟的时间进行排序,0.5分钟的时间进行合并,因此大约需要3分钟。这可能会稍微夸张,因为数据集是按照顺序创建的,所以排序本身的速度可能会稍微快一些(尽管SQL也会从数据集中获得一些)。
这与5e7数据集x的写出时间约5秒相比较。
哈希解决方案将不适合我的笔记本电脑与整体〜6e7记录数据集abc,所以我把它们缩小到总共〜2e7(所以赔率从1到2e7,然后3的倍数从2e7到4e7,然后是从4e7到6e7的4的倍数),但是剩下x有5e7条记录。与排序和合并解决方案相比,散列解决方案总共花费了1·41分钟,而排序和合并解决方案花费了相似的时间,其中大部分是排序x(大约一分钟)并合并/写出结果数据集(大约半分钟) 。这比排序较大的数据集要快得多,因为较小的数据集在内存中排序,而较大的数据集则不能。这些数据集的SQL解决方案大约需要4分钟,所以仍然相当慢。
来源
2012-12-27 14:36:01
Joe
“非常大”有多大? – sasfrog
我们可以安全地假设所有表的行数> 50 M。 –
...多少列?此外,这是你打算做很多次,或一次性的东西?一旦你找到了匹配,你会重新创建X1和X2,还是添加到它们?或者在你检查完X后,X中的行会再次变化吗? – sasfrog