SAS EG proc SQL中的数据集循环

时间:2019-05-16 10:32:51

标签: string loops sas

我是SAS EG的新手,我想知道如何根据SAS EG中的三列值通过循环附加数字。 例如。

Column0   Column1   Column2    Level (desired result)
1A        AA                     0
1A        123AA     AA           1
1A        234AA     123AA        2
2B        BB                     0
2B        123BB     BB           1
2B        234BB     BB           1
2B        345BB     123BB        2
2B        456BB     345BB        3

我只有一个数据集,column0到column2由一个proc sql生成。唯一缺少的是根据column0和column2的值来确定column1的级别。

1 个答案:

答案 0 :(得分:0)

SQL不知道存储在磁盘上的行的顺序,并且您的数据没有附加列用于指示SORTED BY的值。

DATA步骤提供了一种更简单的方法,其中行的顺序是“读取”。由column1键控的哈希对象可以保持先前行的level值,而column2可以用作查找的键值。

例如:

data have;
infile datalines missover;
input
Column0 $ Column1 $ Column2 $; datalines;
1A        AA             
1A        123AA     AA   
1A        234AA     123AA
2B        BB             
2B        123BB     BB   
2B        234BB     BB   
2B        345BB     123BB
2B        456BB     345BB
run;

data want;

  set have;
  by column0;

  if _n_ = 1  then do;
    declare hash lookup();
    lookup.defineKey('column1');
    lookup.defineData('level');
    lookup.defineDone();
  end;

  if first.column0 then
    lookup.Clear();

  if (lookup.find(key:column2) ne 0) then
    level = 0;
  else
    level + 1;

  lookup.add();
run;

注意:以上方法可能需要进行调整才能在VIYA中工作。

在SQL中执行相同操作需要多个步骤。为适当的孩子计算(或发现)每个级别的一个步骤。

proc sql;
  create table level0 as
  select child.*, 0 as level from have as child
  where child.column2 is null;

  %put &=SQLOBS;

  create table level1 as
  select child.*, 1 as level from level0 as parent join have as child
  on parent.column0 = child.column0 and child.column2 = parent.column1;

  %put &=SQLOBS;

  create table level2 as
  select child.*, 2 as level from level1 as parent join have as child
  on parent.column0 = child.column0 and child.column2 = parent.column1;

  %put &=SQLOBS;

  create table level3 as
  select child.*, 3 as level from level2 as parent join have as child
  on parent.column0 = child.column0 and child.column2 = parent.column1;

  %put &=SQLOBS;

  create table level4 as
  select child.*, 4 as level from level3 as parent join have as child
  on parent.column0 = child.column0 and child.column2 = parent.column1;

  %put &=SQLOBS; * 0 obs, so no more children needing parentage found;

  create table want as
  select * from level0 union 
  select * from level1 union
  select * from level2 union
  select * from level3 
  order by column0, level
  ;

一种通用方法必须循环执行,直到SQLOBS为0

  create table level&LOOPINDEX as
  select child.*, &LOOPINDEX as level 
  from level&LOOPINDEX_MINUS_1 as parent 
  join have as child
  on parent.column0 = child.column0 and child.column2 = parent.column1;