我有4张非常大的桌子。我叫他们叫X,A,B和C.
我想从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中的记录匹配。可能这部分与主要问题无关。)
我有两个选项:我可以将X,A,B和C作为Oracle表或SAS数据集。
解决此问题的最有效方法是什么?
此致
答案 0 :(得分: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;
确保'found'和'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中执行此操作,我认为我这样做的方法是更接近tartaglia的解决方案 - 创建三个'匹配'表然后将它们联合起来(删除联合中的重复项),然后创建x2 as x减x1表。 IE(这在SAS的PROC SQL中有效,不确定oracle是否完全相同):
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可能会更好,但应该是类似的顺序 - 但如果你的oracle服务器比你的sas服务器更快,那可能会改变一些事情。)
使用具有5e7记录的数据集'x'和具有公平重叠的三个数据集'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的几率,然后从2e7的3的倍数)到4e7,然后从4e7到6e7的4的倍数,但是左边的x有5e7个记录。然后哈希解决方案总共花费了1:41,与排序和合并解决方案相比,花费了相似的时间,其中大部分是排序x(大约一分钟)并合并/写出结果数据集(大约一分钟) 。这比排序较大的数据集快得多,因为较小的数据集在内存中排序,而较大的数据集则不能排序。这些数据集的SQL解决方案大约需要4分钟,因此仍然要慢得多。
答案 1 :(得分: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重复,如果存在则更改by
和keep
语句
与数据集B和C匹配的不同规则。还将x1_a
和x2_a
的名称更改为x1_b
,依此类推,因此不会被覆盖。
附加所有x1_
表,并在问题中提供X1
数据集(您可能需要处理重复项)。
附加所有x2_
表,并计算不同的行。出现的行数与
您要比较的初始数据集(本例中为3; A,B,C)是您保留的数据集。