Oracle/SAS记录匹配从多个表/数据集



我有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数据集。

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

认为,

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'不是任何原始数据集上的变量,否则使用其他变量唯一复杂的因素是如果你想要一些变量而不是ID from ab c;如果是这样,那么您需要弄清楚如何确保在多个匹配场景中获得正确的变量。还需要对所有四个表进行排序(可能很慢)。

另一个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作为x - x1表。IE(这适用于SAS中的PROC SQL,不确定oracle是否与except完全相同):

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服务器快,这可能会改变一些事情)。

使用一个数据集"x"5 e7记录,和三个数据集的一个"b ' c '与公平重叠(大概25%左右的记录在2个或更多的数据集,和84%的人在一个或多个)和1.5 e7和3之间e7记录在每个(具体地说,一个所有奇数,一个3的倍数,和一个甚至4的倍数),SQL解决了5分钟处理而sort-and-merge解决方案花了约2.5分钟和0.5分钟合并,所以大约3分钟。这可能有点夸张,因为创建的数据集是有序的,所以排序本身可能会更快一些(尽管SQL也会从有序的数据集中获得一些好处)。

相比之下,5e7数据集x的写时间约为5秒。

哈希解决方案不适合我的笔记本电脑的内存,总的~6e7记录数据集abc,所以我把它们缩小到总共~2e7(所以概率从1到2e7,然后从2e7到4e7的3的倍数,然后从4e7到6e7的4的倍数),但留下x有5e7记录。散列解决方案总共花费了1:41的时间,而排序和合并解决方案花费了相似的时间,其中大部分时间是排序x(大约一分钟)和合并/写出结果数据集(大约半分钟)。这比对大数据集进行排序要快得多,因为小数据集在内存中排序,而大数据集不能。对于这些数据集,SQL解决方案大约需要4分钟,因此仍然非常慢。

如果我没理解错的话,你可以这样做:

合并数据集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)是你保留的。

最新更新