在SQL中通过重叠ID对重叠值或日期进行求和/计数

时间:2019-03-13 14:09:58

标签: sql sas proc-sql

我正在使用sas表,日期用列在“ entered”和“ left”列中的数字表示。我必须计算成员保留在系统中的天数。像下面的ID 1一样,该人输入了7071,然后又在7075上使用了另一种产品,尽管他在系统中从7071到7083一直保持连续。这就是日期重叠了。我想计算一个成员在系统中停留的最终持续时间,就像id 1一样,它是12天(7083-7071)+ 2天(7087至7089)+ 4天(7095至7099)。所以总共是18天。 (存在一些重复的输入值和左值,但其他列(此处未显示)不相同,因此未删除这些行。)由于我在sas工作,所以这个想法可以是sas数据或sas-sql格式。

对于成员2,值没有重叠。因此,天数为2(8921至8923)+ 5天(8935至8940)= 7天。我能够解决这种情况,因为日子并不重叠,但是对于重叠的情况,任何建议或代码/建议都值得赞赏。

id  Entered  left
 1    7071   7077
 1    7071   7077
 1    7075   7079
 1    7077   7083
 1    7077   7083
 1    7078   7085
 1    7087   7089
 1    7095   7099
 2    8921   8923
 2    8935   8940

因此,决赛桌的形式应为

id  days_in_system
 1       18
 2       7

1 个答案:

答案 0 :(得分:1)

这是一个非常棘手的问题,因为必须将每行与具有相同id的其他行进行比较以检查重叠,如果有多个重叠,则必须非常小心,不要重复计算它们。

这是一个基于哈希的解决方案-这个想法是建立一个哈希,其中包含成员在您逗留期间停留的所有天数,然后最后计算其中的项数:

data have;
input id  Entered  left;
cards;
 1    7071   7077
 1    7071   7077
 1    7075   7079
 1    7077   7083
 1    7077   7083
 1    7078   7085
 1    7087   7089
 1    7095   7099
 2    8921   8923
 2    8935   8940
 ;
 run;

data want;

length day 8;
if _n_ = 1 then do;
  declare hash h();
  rc = h.definekey('day');
  rc = h.definedone();
end;

do until(last.id);
  set have;
  by id;
  do day = entered to left - 1;
    rc = h.add();
  end;
end;

total_days = h.num_items;
rc = h.clear();
keep id total_days;

run;

这应该在内存上比较轻巧,因为它一次只需要加载1个id的天数即可。

id 1的输出是20,而不是18-这是我逐行添加的新细分的细目,我是通过添加一些调试逻辑来生成的。如果这是错误的,请指出:

_N_=1
7071 7072 7073 7074 7075 7076
_N_=2
No new days
_N_=3
7077 7078
_N_=4
7079 7080 7081 7082
_N_=5
No new days
_N_=6
7083 7084
_N_=7
7087 7088
_N_=8
7095 7096 7097 7098
_N_=1
8921 8922
_N_=2
8935 8936 8937 8938 8939

如果只想为符合特定条件的行添加天数,则可以使用set语句中的where子句来选择那些天数,例如

  set have(where = (var1 in ('value1', 'value2', ...)));