SAS:从一个表插入到另一个表

SAS:从一个表插入到另一个表,sas,Sas,我有一个数据集,我想用单独分析的结果更新它。分析是在循环中进行的。在循环结束时,将使用分析中的值更新主数据集。但是,我很难将新值插入主表 *****************; ** Using Merge **; *****************; data master_merge_copy; set master; run; data master_merge_copy; merge master_merge_copy first_insert

我有一个数据集,我想用单独分析的结果更新它。分析是在循环中进行的。在循环结束时,将使用分析中的值更新主数据集。但是,我很难将新值插入主表

*****************;
** Using Merge **;
*****************;

data master_merge_copy;
  set master;
run;

data master_merge_copy;
  merge master_merge_copy
        first_insert
        ;
  by var1 var2;
run;
data want ;
   merge master all_results;
   by var1 var2;
run;
对于这个例子,我已经删除了循环。此外,我创建了一个副本,而不是覆盖主数据集

主数据集有两个变量,用于确定哪些行需要插入值,即
var1
var2

data master;
  input var1 $ var2 $;

  datalines;
  A A
  A A
  A B
  A B
  ;
run;
由于结果是循环的一部分,因此必须单独执行插入。也就是说,我无法将分析结果合并到一个表中并执行一次合并。我在这里把它们作为两个独立的数据集

data first_insert;
  input var1 $ var2 $ var3 $;

  datalines;
  A A C
  ;
run;

data second_insert;
  input var1 $ var2 $ var3 $;

  datalines;
  A B D
  ;
run;
我的第一种方法是使用
MERGE
语句。但是,当我这样做时,并不是所有的数据都写入主表

*****************;
** Using Merge **;
*****************;

data master_merge_copy;
  set master;
run;

data master_merge_copy;
  merge master_merge_copy
        first_insert
        ;
  by var1 var2;
run;
data want ;
   merge master all_results;
   by var1 var2;
run;
这就像我期望的那样合并,将值
C
放在
var3
中,其中
var1=A和var2=A

Obs    var1    var2    var3
1      A       A       C
2      A       A       C
3      A       B
4      A       B
但是,当我执行第二次合并时,只会写入与合并条件匹配的第一个观察值。我需要它将
var3=D
写入所有观察值,其中
var1=A和var2=B

data master_merge_copy;
  merge master_merge_copy
        second_insert
        ;
  by var1 var2;
run;

                             Obs    var1    var2    var3
                              1      A       A       C
                              2      A       A       C
                              3      A       B       D
                              4      A       B
其次,我尝试使用
UPDATE
语句

******************;
** Using Update **;
******************;
data update_copy;
  set master;
run;

data update_copy;
  update update_copy
         first_insert
         ;
  by var1 var2;
run;
但是,BY组中存在多个观察值会产生错误

WARNING: The MASTER data set contains more than one observation for a BY group.
var1=A var2=A var3=  FIRST.var1=0 LAST.var1=0 FIRST.var2=0 LAST.var2=1 _ERROR_=1 _N_=2
WARNING: The MASTER data set contains more than one observation for a BY group.
var1=A var2=B var3=  FIRST.var1=0 LAST.var1=1 FIRST.var2=0 LAST.var2=1 _ERROR_=1 _N_=4
结果数据集与我预期的不同:

                             Obs    var1    var2    var3

                              1      A       A       C
                              2      A       A
                              3      A       B
                              4      A       B
似乎有一种解决方案可以使用
PROC SQL
INSERT
WHERE
语句。但是,当要插入的值位于单独的表中时,我不清楚如何执行此操作。我能找到的所有示例都声明要显式插入的值。比如说,

proc sql;
   update sql.newcountries
      set population=population*1.05
         where name like 'B%';
quit;
请告知

似乎我们能够在SAS论坛上提供类似问题的答案。SAS SQL的语法让我觉得很奇怪,但下面的方法似乎是可行的

data master;
  input var1 $ var2 $;

  datalines;
  A A
  A A
  A B
  A B
  ;
run;

data first_insert;
  input var1 $ var2 $ var3 $;

  datalines;
  A A C
  ;
run;

data second_insert;
  input var1 $ var2 $ var3 $;

  datalines;
  A B D
  ;
run;

data master_copy;
  set master;
  length var3 $ 8.;
run;

proc sql;
  update master_copy A
  set var3 = ( select var3
  from first_insert
  where A.var2 = var2)
  where var2 in (select var2
  from first_insert);
  ;
quit;

proc sql;
  update master_copy A
  set var3 = ( select var3
  from second_insert
  where A.var2 = var2)
  where var2 in (select var2
  from second_insert);
  ;
quit;

请注意,如果这是在循环内部实现的,请确保仅复制一次
主副本

我不喜欢使用SQL来完成这项工作,因为编写它相当烦人。我也不喜欢使用数据步合并技术(确实存在这种技术),因为它们也很挑剔,很难记住语法,至少对我来说是这样

在我看来,数据步哈希是最好的

data want;
  if 0 then set first_insert;
  if _n_=1 then do;
    declare hash f(dataset:'first_insert');
    f.defineKey('var1','var2');
    f.defineData('var3');
    f.defineDone();
  end;
  call missing(of _all_); *prevents us from getting bit by the automatic RETAIN if `var3` is not on the master dataset;
  set master;
  rc = f.find();

run;

当然,我认为真正的最佳答案是将所有修改存储到末尾,然后将它们追加,如果可以的话,但有时无论出于何种原因,这都是不可行的。

不要插入任何内容。生成新记录并将其附加到正在生成的新结果文件中。首先确保
所有结果都不存在。然后在循环中将当前结果附加到循环中。因此,通过您的示例数据,可以将这些步骤转换为

 proc append base=all_results data=first_insert force;
 run;
 proc append base=all_results data=second_insert force;
 run;
现在,您可以通过将此表与主表合并来创建所需的总体结果

*****************;
** Using Merge **;
*****************;

data master_merge_copy;
  set master;
run;

data master_merge_copy;
  merge master_merge_copy
        first_insert
        ;
  by var1 var2;
run;
data want ;
   merge master all_results;
   by var1 var2;
run;

这是非常标准的SQL语法,因此没有特定于SAS SQL的语法。我会避免在这里使用
insert
,因为您实际上并没有执行大多数人所称的
insert
——您正在合并或更新<代码>插入
在其中通常指添加行,而不是添加列。我不确定我是否理解。为什么要插入任何内容?您不是在制作一个新表来保存您的分析结果吗?@Tom s/insert/update(SAS术语)。OP有一个主表,并且正在使用第三个变量一次更新该主表一点(可能是由于某些分析在某些其他变量上循环)