2013-11-24 67 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