【问题标题】:update statement in data step数据步骤中的更新语句
【发布时间】:2015-08-05 07:58:20
【问题描述】:

在数据库中,我们有如下电子邮件地址数据集。请注意,对于 id 1003 有两个观察结果

data Email;
    input id$ email $20.;
    datalines;
1001 1001@gmail.com
1002 1002@gmail.com
1003 1003@gmail.com
1003 2003@gmail.com
;
run;

我们收到用户要求更改电子邮件地址如下,

data amendEmail;
    input id$ email $20.;
    datalines;
1003 1003@yahoo.com
;
run;

我尝试在数据步骤中使用update 语句

data newEmail;
    update Email amendEmail;
    by id;
run;

虽然它只会更改 id 1003 的第一个观察结果。

我想要的输出是 1001 1001@gmail.com 1002 1002@gmail.com 1003 1003@yahoo.com 1003 1003@yahoo.com

是否可以使用非proc sql方法?

【问题讨论】:

  • 抱歉,您的问题到底是什么?是否要更改两行? (在这种情况下,您只会得到重复的行)

标签: sas datastep


【解决方案1】:

Vasilij 的基于合并的数据步骤答案将为您提供所需的数据集,但不是以最有效的方式,因为它会覆盖整个 email 数据集,而不是仅更新您要更改的行。

您可以使用modify 语句仅更改email 中与amendEmail 数据集中具有匹配ID 的行的电子邮件地址。

首先,您需要确保在 email 数据集中有一个关于 id 的索引。这只是一项一次性任务 - 只要您不覆盖 email 数据集(例如,使用另一个不使用 modify 语句或对其进行排序的数据步骤),索引仍然存在.

proc datasets lib = work nolist;
    modify email;
    index create id;
    run;
quit;

现在您可以使用索引进行更新:

data email;
    set amendEmail(rename = (email = new_email));
    do until(eof);
        modify email key = id end = eof;
        if _IORC_ then _ERROR_ = 0;
        else do;
            email = new_email;
            replace;
        end;
    end;
run;

您应该会在日志中看到如下所示的一些输出,表明您的数据集已被更新而不是被覆盖:

NOTE: There were 1 observations read from the data set WORK.AMENDEMAIL.
NOTE: The data set WORK.EMAIL has been updated.  There were 2 observations rewritten, 0 observations added and 0 observations 
       deleted.

注意在您使用这样的modify 语句之前,请确保您的主email 数据集已备份。如果数据步骤被中断,它可能会损坏。

【讨论】:

    【解决方案2】:

    如果您想更改两行,最终会出现重复。您可能应该首先解决源表中的重复问题。

    如果您需要具有重复结果的有效解决方案,请考虑使用带有 LEFT JOIN 的 PROC SQL 和电子邮件地址的条件子句。

    PROC SQL;
        CREATE TABLE EGTASK.QUERY_FOR_EMAIL AS 
            SELECT t1.id, 
               /* email */
                (CASE WHEN t1.id = t2.id THEN t2.email 
                ELSE t1.email 
                END) AS email 
            FROM WORK.EMAIL t1 
            LEFT JOIN WORK.AMENDEMAIL t2 ON (t1.id = t2.id);
    QUIT;
    

    根据 cmets,如果您更喜欢使用数据步骤,您可以使用以下内容:

    data want (drop=email2);
      merge Email amendEmail (rename=(email=email2));
      by id;
      if email2 ne "" then email=email2; 
    run;
    

    【讨论】:

    • 非常感谢您的回答!我想知道是否有非proc sql数据步骤可以实现?
    【解决方案3】:

    理想情况下,您应该在 by 变量中具有唯一值。如果出现重复,它只会更新第一个观察结果。请参考以下链接 http://support.sas.com/documentation/cdl/en/basess/58133/HTML/default/viewer.htm#a001329152.htm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      相关资源
      最近更新 更多