多个变量和宏

时间:2015-06-17 13:02:37

标签: macros sas

我希望有人能够帮助我。我有一些相当冗长的SQL代码,它提取了一些信息,包括销售和网络数据。我需要在多个城市运行它。但是,不是多次重新运行代码,而是每次手动更改城市。我想知道我是否可以使用宏,以便代码只写一次,但是城市是某种类型的宏变量,当代码运行时,它会读出一个感兴趣的城市表,输出将是一个表对于每一个。

为了把事情放到上下文中,下面是代码的摘录,您可以在其中看到变量' City'这是'伦敦'对于这个例子。

rsubmit;
proc sql; 
    create table help as 
        select distinct a.customer_id, max(a.level) as level, a.london
            from (
                select distinct customer_id, max(SESSION_DT) as session_dt format date9., TXT,
                    case when TXT in ('Gold') then 1
                         when TXT in ('Silver') then 2
                         when TXT in ('Bronze') then 3
                         else 4 end as level,
                    case when customer_id is not null then "3" else '' end as London
                        from search_data
                            where CITY in ('London') and TXT is not null
                                group by 1) a
group by 1;
quit;
endrsubmit;

2 个答案:

答案 0 :(得分:2)

您确定可以将城市名称字符串放入宏变量中,然后将其解析出来,但是,它将具有64K字节的长度限制以及宏编程的复杂性。以下是我在这种情况下会做的事情: 1.将主代码放入宏中 2.将所有城市名称放入SAS表中。 3.使用CALL EXECUTE()动态调用宏。

%macro test(city=London);
rsubmit;
proc sql; 
    create table help as 
        select distinct a.customer_id, max(a.level) as level, a.london
            from (
                select distinct customer_id, max(SESSION_DT) as session_dt format date9., TXT,
                    case when TXT in ('Gold') then 1
                         when TXT in ('Silver') then 2
                         when TXT in ('Bronze') then 3
                         else 4 end as level,
                    case when customer_id is not null then "3" else '' end as London
                        from search_data
                            where CITY eq "&city." and TXT is not null
                                group by 1) a
group by 1;
quit;
endrsubmit;
%mend;

data _null_;
set cities; /*this is where you store city names in a variable named CITY, one per row*/
call execute ('%test (city= '||city ||')' );
run;

答案 1 :(得分:1)

如果我正确理解您的代码,您可以在一个SQL步骤中完成所需的操作,而不是尝试使用宏遍历城市:

proc format;
    value $level.
        'Gold' = 1
      'Silver' = 2
      'Bronze' = 3
         other = 4
         ;

      value customer_city
              . = ''
          other = 3
             ;

run;

proc sql;
    create table help as
    select
       distinct customer_id
     , city
     , max(session_id) as session_id
     , max(put(TXT, $level.)) as level
     , put(customer_id, customer_city.) as customer_city
    from search_data
    where TXT is not null
    group by customer_id, city
    ;
quit;

这里" customer_city"取而代之的是你所拥有的" a.London"," a.Tokyo"等

没有" search_data"的描述以及你想要的输出的一个例子,我无法自信地说这段代码将完全符合您的要求 - 它甚至可能会出现一些错误。但是你应该能够适当地修改它并一步完成所有的摘要。

在您的方法中,SQL循环遍历search_data一次,然后再循环遍历聚合数据。那么你将不得不为你拥有的每个城市做到这一点。换句话说,您扫描数据集的次数约为2 *城市数量。如果search_data很大,这将比在一个SQL步骤中执行此操作慢得多。

如果你真的需要为每个城市提供一个单独的表,那么你可以用这个宏拆分它们:

%macro subset_city(data, city);

   data &city._table(rename=(customer_city=&city.));
       set &data.;

       where city = &city.;
    run;

%mend subset_city;

data _null_;
    set list_of_cities;

     call execute ('%subset_cities(data =help, city= '||city ||')');
run;