【问题标题】:Populate SAS macro-variable using a SQL statement within another SQL statement?使用另一个 SQL 语句中的 SQL 语句填充 SAS 宏变量?
【发布时间】:2021-03-21 07:10:43
【问题描述】:

我偶然发现了以下代码 sn-p,其中变量 top3 必须从表 have 中填充,而不是从数字数组中填充。

%let top3 = 14 15 42; /* This should be made obsolete.. */
%let no = 3;

proc sql;
   create table want as
   select *
   from (select x, y from foo) a
   %do i = 1 %to &no.;
     %let current = %scan(&top3.,&i.);   /* What do I need to put here? */
     left join (select x, y from bar where z=&current.) row_&current.
     on a.x = row_&current..x
   %end;
   ;
quit;

have 包含字符串中的xs,如下所示:

i   x
1   14
2   15
3   42

我现在想知道如何修改%let current = ... 行,以便从表have 填充current。我知道如何使用proc sqlselect .. into 填充宏变量,但恐怕我现在的做法完全违背了SAS 哲学。

【问题讨论】:

  • 为什么原始查询使用 %DO 循环而不是仅仅执行 select x, y from bar where z in (&top3) ?您不能有多个名为 Y 的变量,您是否过度简化了示例?

标签: sas


【解决方案1】:

看起来你或多或少地转换了一些东西。如果是这样的话,这在macro/sql 中很容易实现。

首先,这是简单的版本 - 没有宏。

proc sql;
  create table class_t as
  select * from (
    select name from sashelp.class ) class
        left join (
          select name, age as age_Alfred
          from sashelp.class 
          where name='Alfred') Alfred
          on class.name = Alfred.name
  ;
quit;

我们从 Alfred 行中获取 age 的值并将其放在主连接中。这不完全是你在做什么,但它看起来很相似。 (我只用了一张,这里当然可以用两张。)

现在,我们如何将其扩展为表格驱动而不是手写?宏!

首先,这里是宏 - 只是采用 Alfred 的部分并使其具有通用性。

%macro joiner(name=);
    left join (
          select name, age as age_&name.
          from sashelp.class 
          where name="&name.") &name.
          on class.name = &name..name
%mend joiner;

其次,我们看看这个,看看我们需要放入宏列表中的两件事:SELECT 变量列表(我们将为每次调用获取一个新变量)和 JOIN 列表。

proc sql;
  select cats('%joiner(name=',name,')')
    into :joinlist separated by ' '
    from sashelp.class;
  select cats(name,'.age_',name)
    into :selectlist separated by ','
    from sashelp.class;   
quit;

然后,我们就叫它吧!

proc sql;
  create table class_t as
    select class.name,&selectlist. from (
        select name from sashelp.class) class
        &joinlist.
    ;
quit;

现在,您从中调用宏列表的数据集可能是上面包含 3 行的数据集(“拥有”)。您实际从中获取附加数据的数据集是其他数据集(“条形图”),对吗?然后你加入的可能是第三个数据集(“foo”)。这里我只使用一个,为简单起见,但概念是一样的,只是来源不同。

【讨论】:

  • 我不明白&selectlist. 如何正确填写您的代码。我希望(在只有Alfred 的情况下)是Alfred.age_Alfred 和完整的连接件,由您的宏%joiner() 返回。我在这里忽略了什么吗?
【解决方案2】:

当查找数据在表中时,您可以执行三向连接,而无需任何 SAS 宏。您不提供任何数据,因此该示例将模拟一些数据。

例子:

假设一个主记录有多个关联的详细记录,并且详细记录包含一个z 值,用于根据所需的z 查找表选择结果集。

data masters;
  call streaminit(2020);

  do id = 1 to 100;
    do x = 1 to 100;
      m_rownum + 1;
      code = rand('integer', 10,45);
      output;
    end;
  end;
run;

data details;
  call streaminit(2020);
  do date = 1 to 20;
    do x = 1 to 100;
      do rep = 1 to 5;
        d_rownum + 1;
        amount = rand('integer', 100,200);
        z = rand('integer', 10,45);
        output;
      end;
    end;
  end;
run;

data zs;
input z @@; datalines;
14 15 42
;

proc sql;
  create table want as
  select
    m_rownum
  , d_rownum
  , masters.id
  , masters.x
  , masters.code
  , details.z
  , details.date
  , details.amount
  from
    masters
  left join 
    details
  on
    details.x = masters.x
  inner join
    zs
  on 
    zs.z = details.z
  order by
    masters.id, masters.x, details.z, details.date
  ;
  quit;

【讨论】:

    猜你喜欢
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多