【问题标题】:select only a few columns from a large table in SAS仅从 SAS 中的大表中选择几列
【发布时间】:2015-10-25 06:29:53
【问题描述】:

我必须在一个键上加入 2 个表(比如 XYZ)。我必须使用合并函数更新表 A 中的一列。合并(a.status_cd,b.status_cd)。

表 A:
包含大约 100 列。关键列 ABC。

表 B: 仅包含 2 列。 KEY 列 ABC 和 status_cd

我在这个左连接查询中使用的表 A 有超过 100 列。有没有办法在我的 PROC SQL 中使用 a.* 后跟这个 coalesce 函数,而无需从 PROC SQL 创建新列;将表创建为 ... 步骤?

提前致谢。

【问题讨论】:

    标签: sas proc-sql


    【解决方案1】:

    您可以利用数据集选项来制作它,以便在 select 语句中使用通配符。请注意,这样做可能会改变列的顺序。

    proc sql ;
      create table want as
        select a.*
             , coalesce(a.old_status,b.status_cd) as status_cd
        from tableA(rename=(status_cd=old_status)) a
        left join tableB b
          on a.abc = b.abc
      ;
    quit;
    

    【讨论】:

    • 这会替换整个表还是只更新相关值?
    • 嗨,Tom,status_cd 列已经存在于以别名“a”引用的表中(列名不是 old_status)。我想我的查询会失败。我将进行更改、测试并确认。
    • 这就是 RENAME= dataset 选项的作用。它会在进入的过程中重命名变量。因此,如果名称是 STATUS_CD,那么 rename 选项会将名称更改为 OLD_STATUS。
    • 谢谢汤姆。有效。我认为它会出错,因为 OLD_STATUS 和 NEW_STATUS 列名是相同的。但它仍然有效。非常感谢。
    • user667489 - 它替换了整个表,但我不需要给出所有列,它变得非常简单。谢谢您的回答。他们对 DATA 步骤和更新表语法提供了深刻的见解
    【解决方案2】:

    在尝试了几种更复杂的方法后,我最终在proc sql 中找到了一种相当简单的方法:

    proc sql noprint;
      update master a
      set status_cd= coalesce(status_cd,
                               (select status_cd
                                from transaction b
                                where a.key= b.key))
      where exists (select 1
                    from transaction b
                    where a.ABC = b.ABC);
    quit;              
    

    这将只更新您感兴趣的一列,并且只会更新其键值与交易数据集中匹配的行。

    早期尝试:

    更通用的 SQL 语法中最明显的一点似乎是this question 的前几个答案中使用的update...set...from...where 模式。但是,目前不支持此语法 - SQL update statement 的文档仅允许 where 子句,而不是 from 子句。

    如果您正在对另一个支持此语法的数据库运行直通查询,它可能仍然是一个可行的选择。

    或者,有一种方法可以在 SAS 中通过数据步骤执行此操作,前提是主数据集在您的关键变量上建立索引:

    /*Create indexed master dataset with some missing values*/
    data master(index = (name));
      set sashelp.class;
      if _n_ <= 5 then call missing(weight);
    run;
    
    /*Create transaction dataset with some missing values*/
    data transaction;
      set sashelp.class(obs = 10 keep = name weight);
      if _n_ > 5 then call missing(weight);
    run;
    
    data master;
      set transaction;
      t_weight = weight;
      modify master key = name;
      if _IORC_ = 0 then do;
          weight = coalesce(weight, t_weight);
          replace;
      end;
      /*Suppress log messages if there are key values in transaction but not master*/  
      else _ERROR_ = 0; 
    run;
    

    modify 语句相关的标准警告:如果此数据步骤被中断,则主数据集可能会受到不可挽回的损坏,因此请确保先备份。

    在这种情况下,我假设关键变量是唯一的 - 如果不是,则需要稍微复杂一点的数据步骤。

    解决proc sql update 语句中缺少from 子句的另一种方法是设置格式合并,例如

    data v_format_def /view = v_format_def;
        set transaction(rename = (name = start weight = label));
        retain fmtname 'key' type 'i';
        end = start;
    run;
    
    proc format cntlin = v_format_def; run;
    
    proc sql noprint;
        update master 
            set weight = coalesce(weight,input(name,key.))
            where master.name in (select name from transaction);
    run;
    

    在这种情况下,我在格式定义中使用了type = 'i' 来创建数字信息,proc sql 使用该信息将字符变量name 转换为数字变量weight。根据您的 keystatus_cd 列是字符还是数字,您可能需要稍微不同地执行此操作。

    这种方法在使用该格式时有效地将整个交易数据集加载到内存中,如果您有一个非常大的交易数据集,这可能会出现问题。数据步骤方法几乎不应该使用任何内存,因为它一次只需要加载 1 行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      相关资源
      最近更新 更多