2012-12-27 47 views
1

我有4个非常大的表。让我给他们打电话X,A,B和C来自多个表/数据集的Oracle/SAS记录匹配

我想创建从X两个表X1和X2如下:

考虑表X的记录r如果R有相应的记录至少有一个表A,B和C,我把它放在X1中。否则我把它放在X2中。

(我如何确定r在A,B或C中有相应的记录?我将r的几个字段与A,B或C中的某些记录的几个字段进行比较。字段可能与A ,B或C,并且可能有多个条件将r与A,B或C中的记录进行匹配。可能这个部分与主要问题没有关系。)

我有两个选项:I can将X,A,B和C作为Oracle表或SAS数据集。

解决此问题的最有效方法是什么?

问候,

+0

“非常大”有多大? – sasfrog

+0

我们可以安全地假设所有表的行数> 50 M。 –

+0

...多少列?此外,这是你打算做很多次,或一次性的东西?一旦你找到了匹配,你会重新创建X1和X2,还是添加到它们?或者在你检查完X后,X中的行会再次变化吗? – sasfrog

回答

1

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分钟,所以仍然相当慢。

0

如果我理解正确的话,你可以做这样的事情:

合并数据集X和A上要找到匹配的变量从X 输出记录匹配的是将表格A记录到X1中,并将不匹配 的记录输出到X2中。

比方说,你正在处理的示例数据集的X和A:

data x; 
input id some_value $; 
datalines; 
1 a 
2 b 
3 c 
4 d 
5 e 
run; 

data a; 
input id some_value $ some_value_2 $; 
datalines; 
1 a x 
4 d v 
5 g u 
run; 

现在,你可以做一个合并这样的:

data x1_a x2_a; 
merge x(in=table_x) a(in=table_a keep=id some_value); 
by id some_value; 
if table_x = 1 and table_a = 1 then output x1_a; 
if table_x = 1 and table_a = 0 then output x2_a; 
run; 

重复的数据集B和C,改变bykeep声明如果有 与数据集B和C匹配的不同规则。同时将x1_ax2_a的名称更改为x1_b等,因此它们不会得到覆盖。

追加所有x1_表,并且您有问题中描述的X1数据集(您可能需要处理重复项)。

追加所有x2_表,并计算不同的行。行的数量与 的次数完全相同,您正在比较的初始数据集(在这种情况下为3,A,B,C)是您保留的数据集。

相关问题