【问题标题】:Multiple Variables and Macros多个变量和宏
【发布时间】:2015-06-17 13:02:37
【问题描述】:

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

为了把事情放在上下文中,下面是代码的摘录,您可以在其中看到变量“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 in ('London') and TXT is not null
                                group by 1) a
group by 1;
quit;
endrsubmit;

【问题讨论】:

    标签: macros sas


    【解决方案1】:

    您当然可以将城市名称字符串放入宏变量中,然后将它们解析出来,但是它会带来 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;
    

    【讨论】:

    • 谢谢,这很有帮助。真的很感激。
    【解决方案2】:

    如果我正确理解您的代码,您可以在一个 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*Number of Cities。如果 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;
    

    【讨论】:

    • 谢谢。这有助于我的理解。我真的很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    相关资源
    最近更新 更多