SAS Proc SQL中的列表聚合和组串联

时间:2019-04-15 19:56:54

标签: sas proc-sql

我有一个必须根据粒度(FIELD1和FIELD2)汇总的数据集。必须对两个指标字段(METRIC1和METRIC2)进行汇总。到目前为止,这似乎是一个简单的GROUP BY任务。但是我有一个字符串字段(FLAG),也必须通过串联不同的值来汇总。

输入数据集:

enter image description here

预期结果:

enter image description here

可以在Oracle中使用LISTAGG()函数执行此操作。 请帮助我在SAS Proc SQL中实现相同的目标。

3 个答案:

答案 0 :(得分:2)

我不认为在SAS中有直接的方法。 CATS(和类似的串联功能)不是聚合功能。有人建议将这些添加回几年前,但我所知道的什么都没有(请参阅this thread。)

如果我理解正确,您正在做的是GROUP BY field1 / field2,SUM metric1 / metric2,并创建一个将所有可见的FLAG字段值(但不按其分组)的FLAG字段。

我要处理的方式是先进行聚合(field1 / field2),然后将其加入到单独的表中,该表只是field1 / field2 / flag。您可以在数据步骤中最轻松地做到这一点,例如:

data want;
  set have;
  by field1 field2;
  length flag_out $100; *or longer if you need longer;
  flag_out = catx(',',flag_out,flag);
  if last.field2 then output;
  rename flag_out=flag;
  drop flag;
run;

这假设它已经按field1 / field2进行了排序,否则您需要先进行此操作。

答案 1 :(得分:1)

如上所述,没有LISTAGG()函数,也没有用于创建自定义聚合函数的内置功能。但是,有两种可能性可以得到输出。

示例一

具有DOW处理和散列的数据步骤,用于在组内并置时跟踪不同的标志值。

data want;
  if 0 then set have; *prep pdv;
  length flags $200;

  declare hash _flags();
  _flags.defineKey('flag');
  _flags.defineDone();

  do until (last.f2);
    set have;
    by f1 f2;
    m1_sum = sum(m1_sum,m1);
    m2_sum = sum(m2_sum,m2);
    if _flags.find() ne 0 then do;
      _flags.add();
      flags = catx(',',flags,flag);
    end;
  end;

  drop m1 m2 flag;

  _flags.delete();
run;

示例二

创建从SQL内部使用的FCMP自定义函数。由于FCMP无法创建聚合函数,因此结果将自动与原始数据合并,然后必须对其进行过滤。 FCMP函数还使用散列来跟踪组中flag的不同值。

proc fcmp outlib=sasuser.functionsx.package;

  function listagg(f1 $, f2 $, n, item $) $;
    length result $32000 index 8;

    static flag;
    static index;
    declare hash items();

    if flag = . then do;
      flag = 1;
      rc = items.defineKey('item');
      rc = items.defineDone();
    end;

    static items;

    index + 1;
    rc = items.replace();

    if index = n then do;
      declare hiter hi('items');
      result = '';
      do while (hi.next() = 0);
       result = catx(',',result,item);
      end;

      index = 0;
      rc = items.clear();

      return (result);
    end;
    else 
      return ("");

  endsub;
run;

options cmplib=sasuser.functionsx;

proc sql;
  create table wanted as 
  select * from 
  (
    select                      /* subselect is a remerge due to 'listagg' mimic */
      f1, 
      f2,
      listagg(f1, f2, count(*), flag) as flags,
      sum(m1) as m1,
      sum(m2) as m2
    from have
    group by f1, f2
  )
  where flags is not null                   /* filter the subselect */
;
quit;

理想情况下,将使用哈希哈希,但是FCMP仅在declare语句中提供哈希实例的创建,而动态哈希不能用_new_实例化。 SAS Viya用户将能够在FCMP功能中使用新的组件对象Dictionary,并且可能具有字典词典来跟踪每个组中不同的标志值。 / p>

答案 2 :(得分:0)

感谢大家的宝贵意见。显然,SAS中没有针对此方案的直接解决方案。考虑到需求的整体情况,我决定在数据层本身解决问题,或添加另一个中间表示层。 我敢肯定,很多人已经指出了SAS的这一需求,我也曾提出过SAS这个问题。希望他们研究一下并提出与LISTAGG或GROUP_CONCAT类似的功能。