2013-11-24 35 views
0

我知道标题有点难以理解,我很抱歉。找不到更好的方式来解释我的问题。将行添加到使用前一行的当前密钥

我有这样的事情:

DATA HAVE; 
INPUT POLID PRODID TOSNUM PREMID X_INSURER_SERIAL_NO; 
DATALINES; 
13102100206 310 0 20 . 
13102100207 310 0 20 . 
13102100207 310 0 21 . 
13102100207 310 1 1 . 
13102100207 310 1 2 . 
13102100207 310 1 3 . 
13102100207 310 1 20 . 
13102100207 310 1 21 . 
13102100207 310 2 1 . 
13102100207 310 2 2 . 
13102100207 310 2 20 . 
13102100207 310 2 21 . 
13102100207 310 3 1 . 
13102100207 310 3 2 . 
13102100207 310 3 9 . 
13102100207 310 3 20 . 
13102100207 310 3 21 . 
13102100209 310 500 20 5 
13102100210 310 100 20 1 
13102100210 310 101 21 1 
13102100210 310 100 1 1 
13102100210 310 101 2 1 
13102100210 310 101 3 1 
13102100211 310 100 20 1 
13102100211 310 101 21 1 
13102100211 310 200 1 2 
13102100211 310 201 2 2 
13102100211 310 201 3 2 
;RUN; 

我需要做的是,

附加premid如果丢失当前行中,但上一行存在了每polid +的产品编号。

例如, polid = 13102100207,PRODID = 310

当tosnum = 1,I有5种不同的premid(1,2,3,20,21)。 当tosnum = 2时,我有4个不同的前体(1,2,20,21)。 premid = 3缺失。

我需要添加此前贴图,并在fictive_ind列中添加1,每当添加前贴图时。

polid = 13102100206,例如, 只有一行,并且因为它没有以前的tosnum,所以排除在计算之外。

当X_INSURER_SERIAL_NO没有丢失时,它应该替换tosnum。

所以, 例如,polid = 13102100210 sholud从计算, 已排除以及它不具有任何其他先前的值(x_insurer_serial_no总是等于1)。

这是我做了什么:

首先,更换时x_insurer_serial_no不缺少tosnum:

PROC SQL; 
CREATE TABLE AAA 
AS 
SELECT DISTINCT POLID, PRODID , 
CASE WHEN X_INSURER_SERIAL_NO = . THEN TOSNUM ELSE X_INSURER_SERIAL_NO END as X_INSURER_SERIAL_NO 
FROM HAVE 
;QUIT; 

然后,

我用下面的代码,如果polid找出包括或不包括sholud:

PROC SQL; 
CREATE TABLE BBB AS 
SELECT POLID, PRODID, COUNT(*) AS COUNT 
FROM AAA 
GROUP BY 
POLID, PRODID 
;QUIT; 

我只考虑count> 1的计算行。

PROC SQL; 
CREATE TABLE ABC AS 
SELECT * FROM HAVE 
WHERE 
CATS(POLID,PRODID) IN 
SELECT CATS(POLID,PRODID) FROM BBB 
WHERE COUNT>1; 
QUIT; 

现在我发现最小值和最大值为循环:

proc sql; 
select min(TOSNUM), max(TOSNUM) , max(TOSNUM) - min(TOSNUM) into: min_TOSNUM, :max_TOSNUM, :diff 
from abc; 
quit; 

然后循环:

%宏fictive_premid(min_TOSNUM =,DIFF =);

proc sql; 创建表fictive_premid 作为选择POLID,PRODID,TOSNUM,PREMID,0作为FICTIVE_IND 从ABC 其中TOSNUM = & min_TOSNUM; quit;

%do i = &min_TOSNUM %to %eval(&diff-1) ; 
    proc sql; 
    create table fictive_premid_t as 
    select * from 
    (
    select polid, prodid, %eval(&i+1) as TOSNUM, premid, 1 as FICTIVE_IND 
    from fictive_premid 
    where TOSNUM = &i 
    except 
    select polid, prodid, %eval(&i+1) as TOSNUM , premid, 1 as FICTIVE_IND 
    from abc 
    where TOSNUM = %eval(&i+1) 
    ) 
    union 
    select polid, prodid,%eval(&i+1) as TOSNUM, premid, 0 as FICTIVE_IND 
    from abc 
    where TOSNUM = %eval(&i+1); 
    quit; 

    proc append base=fictive_premid data=fictive_premid_t; run; 

%end; 


by polid prodid TOSNUM premid 
%mend; 


%fictive_premid (min_TOSNUM = &min_TOSNUM, diff = &diff); 

现在,

我的问题begings,例如,当 的&值i = 4 和polid = 13102100207 ....

去年tosnum等于3, 我得到6个新的行,其中tosnum = 4,fictive_ind = 1。 这发生了,当然,直到&我达到& diff的值。

什么,我问你,请

是一种方式,当到达最后tosnum或x_insurer_serial_no停止itterating。

非常感谢您的帮助。

Hopefuly我解释说我的需求够好。

回答

1

如果我理解你的问题,我认为这是你想要的。这依赖于TOSNUM值是增量的(即1,2,3或4,5,6)而没有跳过。

/*Overwrite TOSNUM with X_INSURER_SERIAL_NO 
    if it exists*/ 
data have; 
set have; 
tosnum = coalesce(X_INSURER_SERIAL_NO,TOSNUM); 
run; 

proc sort data=have; 
by POLID PRODID TOSNUM PREMID; 
run; 

proc sql noprint; 
/*Find polid values to delete*/ 
create view dist as 
select distinct polid, 
     prodid, 
     tosnum 
    from have; 

create table toDelete as 
    select polid, 
      count(*) as count 
     from dist 
     group by polid 
     having count = 1; 

/*Delete single values*/ 
delete from have 
    where polid in 
     (select polid from toDelete); 

create table lastTosnum as 
select POLID, PRODID, max(TOSNUM)+1 as Tosnum 
    from have 
    group by POLID, PRODID; 
quit; 

/*Increment TOSNUM by 1*/ 
data nextVals; 
set have(drop=X_INSURER_SERIAL_NO); 
TOSNUM = tosnum + 1; 
run; 

/*Delete the last TOSNUM from the set above*/ 
proc sql noprint; 
delete from nextVals as nv 
    where nv.tosnum in 
     (select tosnum 
      from lastTosnum as lts 
      where lts.polid = nv.polid 
       and lts.prodid = nv.prodid 
     ); 
quit; 

/*Merge to get the final set.*/ 
data want; 
merge have (in=h) nextVals (in=next); 
by POLID PRODID TOSNUM PREMID; 

if next and ^h then 
    fictive_ind = 1; 
else 
    fictive_ind = 0; 
/*decrement tosnum*/ 
tosnum = tosnum-1; 

run; 
+0

首先,非常感谢您的回复。解决方案的问题(也是我的,实际上......)是,我必须保持每一行的原始tosnum ...当我意识到我有一个巨大的问题时,我已经完成了对代码的写入。不知道该怎么做才能说实话:( – user2518751

+1

刚回到这里,对于延迟感到抱歉,如果TOSNUM的值是递增的,就像我想的那样,你可以在最后一个数据中加上'TOSNUM = TOSNUM-1'我编辑了解决方案来显示这个。 – DomPazz

+0

非常感谢。 – user2518751