SAS EG如何为唯一列组合执行条件求和?

时间:2015-11-19 16:03:26

标签: sql sas

我正在尝试为人员和时间的每个唯一组合对与代码列值匹配的值列值求和。这个概念应该很简单,但我似乎无法管理......:

INPUT TABLE:

Time   |  Person  |   Value|  Code
_____________________________________
1 | A | 10 | Z1    
1 | A | 11 | Z2    
1 | A | 12 | Z3    
1 | A | 13 | Z4    
1 | A | 20 | Z5    
2 | A | 23 | Z1    
2 | A | 21 | Z2    
2 | A | 33 | Z3    
2 | A | 32 | Z4    
2 | A | 37 | Z5    
1 | B | 38 | Z1    
1 | B | 43 | Z2    
1 | B | 12 | Z3    
1 | B | 13 | Z4    
1 | B | 10 | Z5    
2 | B | 10 | Z1    
2 | B | 11 | Z2    
2 | B | 22 | Z3    
2 | B | 23 | Z4    
2 | B | 10 | Z5

等..................更多的人,时间和代码。

我想对code-column = Z1Z3的值列求和。对于Code = Z2Z4Z5等每个人,每次都没有代码中的结构我总结。

所以输出会是这样的:

Time   |  Person  |   NewValue|  NewCode
_____________________________________
1 | A | 22 | "Z1+Z3"
1 | A | 43 | "Z2+Z4+Z5"
1 | B | 50 | "Z1+Z3"
1 | B | 66 | "Z2+Z4+Z5"
2 | A | 56 | "Z1+Z3"
2 | A | 90 | "Z2+Z4+Z5"
2 | B | 32 | "Z1+Z3"
2 | B | 44 | "Z2+Z4+Z5"

等..................

我希望这个概念很清楚 - 我希望根据代码列对每个独特的人 - 时组合进行求和。我想要总结的代码没有逻辑。 (Z2+Z4,或Z10+Z11+Z12+Z17Z16+Z20等代码也可以多次使用。我只是有一个手动不断变化的列表,其中包含要汇总的代码。)< / p>

到目前为止,我尝试了很多方法,例如:

PROC SQL;
    CREATE TABLE output AS
    SELECT value FROM input
    WHERE code = "Z1" + value WHERE code = "Z3"
    AND time=time AND person=person;
QUIT;

虽然这是语法乱码,但它确实说明了我正在尝试的内容。

2 个答案:

答案 0 :(得分:0)

由于您总是手动创建新值,因此您可以在外部文件中保留要求总和的列表。

File: Combination.xlsx

Combination
Z1 Z2 Z3
Z1 Z4
Z2 Z5
...

接下来,创建一个程序,读取这些组合并将它们保存到宏变量中。您可以使用SQL过滤每个组合。

proc import file='C:\Location\Combination.xlsx'
            out=_Import_Combination
            dbms=xlsx
            replace;
run;

下面将创建一个新变量,将您的组合转换为IN()语句的正确语法。例如"Z1","Z3","Z5"

data Combination;
   set _Import_Combination;

   do i = 1 to countw(Combination);
       if(i = 1) then Filter = quote(scan(Combination, i) );
           else Filter = catt(Filter, ",", quote(scan(Combination, i) ) );
   end;
run;

接下来,将组合名称和过滤器保存到宏变量中。

proc sql noprint;
      select Combination
           , Filter
           , count(*)
      into :combos separated by '|',
           :filter separated by '|',
           :total_combos
      from Combination
      ;
quit;

最后,循环遍历您需要的所有组合。您可以使用SQL过滤每个组合。

%macro countAllCombos;
    %do i = 1 %to &total_combos;
        %let current_combo = %scan(&combos, &i, |);
        %let current_filter = %scan(%bquote(&filter), &i, |);

        proc sql noprint;
             create table %sysfunc(tranwrd(&current_combo, %bquote( ), _) ) as
                   select Time
                        , Person
                        , NewCode
                        , sum(Value) as Total_Value
                   from input
                   where code IN(&current_filter)
                   group by Time, Person
              ;
        quit;
   %end;
%mend;

%countAllCombos;

最终输出将是存储在名为:

的WORK库中的表
Z1_Z2_Z3
Z1_Z4
Z2_Z5
...

答案 1 :(得分:0)

找到解决方案。最简单,最快捷的方法是首先将INPUT表转换为“按人员和时间进行分组分析”,使用“代码”作为“新列名”,将值作为“转置变量”。

接下来,您可以使用以下内容来总结您想要的w / e代码:

%_eg_conditional_dropds(WORK.OUTPUT); 

PROC SQL;
       CREATE TABLE WORK.OUTPUT(label="OUTPUTname") AS 
       SELECT t1.Person, 
              t1.Time, 
                (SUM(t1.'Column Z1'n,t1.'Column Z3'n)) AS 'NewCode 1'n, 
                (SUM(t1.'Column Z2'n,t1.'Column Z4'n,t1.'Column Z5'n)) AS 'NewCode2'n
    QUIT;

这甚至可以通过使用算术而不是“sum”命令来扩展和简化,例如:

/*Instead of*/
(SUM(t1.'Column Z1'n,t1.'Column Z3'n)) AS 'NewCode 1'n,
/*do stuff like:*/
t1.'Column Z1'n + t1.'Column Z3'n - (t1.'Column Z3'n - t1.'Column Z5'n) AS 'NewCode 1'n,
/*etc.*/