1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-22 02:31:19 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
^
862b1896fe feat: adding filtervar option to mp_stripdiffs 2024-04-30 18:31:26 +01:00
^
22f0cb67a5 fix: handling consecutive add+delete in mp_stripdiffs 2024-04-30 17:38:36 +01:00
^
e6da373853 fix: more dedup fixes on mp_stripdiffs 2024-04-30 14:04:15 +01:00
2 changed files with 102 additions and 52 deletions

77
all.sas
View File

@@ -13407,6 +13407,8 @@ run;
change, plus ALL SUBSEQUENT CHANGES, will be reverted in the output table. change, plus ALL SUBSEQUENT CHANGES, will be reverted in the output table.
@param [in] difftable The dataset containing the diffs. Definition available @param [in] difftable The dataset containing the diffs. Definition available
in mddl_dc_difftable.sas in mddl_dc_difftable.sas
@param [in] filtervar= (0) If provided, the contents of this macro variable
will be applied as an additional filter against &libds
@param [out] outds= (work.mp_stripdiffs) Output table containing the diffs. @param [out] outds= (work.mp_stripdiffs) Output table containing the diffs.
Has the same format as the base datset, plus a Has the same format as the base datset, plus a
`_____DELETE__THIS__RECORD_____` variable. `_____DELETE__THIS__RECORD_____` variable.
@@ -13415,7 +13417,9 @@ run;
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarlist.sas
@li mf_islibds.sas @li mf_islibds.sas
@li mf_wordsinstr1butnotstr2.sas
@li mp_abort.sas @li mp_abort.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@@ -13432,6 +13436,7 @@ run;
%macro mp_stripdiffs(libds %macro mp_stripdiffs(libds
,loadref ,loadref
,difftable ,difftable
,filtervar=0
,outds=work.mp_stripdiffs ,outds=work.mp_stripdiffs
,mdebug=0 ,mdebug=0
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -13455,11 +13460,11 @@ run;
,msg=%str(Invalid library.dataset reference - %superq(libds)) ,msg=%str(Invalid library.dataset reference - %superq(libds))
) )
/* set up unique and temporary vars */ /* set up unique and temporary vars */
%local ds1 ds2 ds3 ds4 ds5 fref1; %local ds1 ds2 ds3 ds4 ds5 fref1 filterstr;
%let fref1=%mf_getuniquefileref(); %let fref1=%mf_getuniquefileref();
%if &filtervar ne 0 %then %let filterstr=%superq(&filtervar);
%else %let filterstr=%str(1=1);
/* get timestamp of the diff to be reverted */ /* get timestamp of the diff to be reverted */
%local ts; %local ts;
@@ -13482,30 +13487,28 @@ create table &ds1 (drop=libref dsn) as
/* extract key values only */ /* extract key values only */
%let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_pks)); %let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_pks));
%local keyhash processed;
%let keyhash=%upcase(%mf_getuniquename(prefix=mpsdvar_keyhash));
%let processed=%upcase(%mf_getuniquename(prefix=mpsdvar_processed));
create table &ds2 as create table &ds2 as
select key_hash, select key_hash as &keyhash,
tgtvar_nm, tgtvar_nm,
tgtvar_type, tgtvar_type,
coalescec(oldval_char,newval_char) as charval, coalescec(oldval_char,newval_char) as charval,
coalesce(oldval_num, newval_num) as numval, coalesce(oldval_num, newval_num) as numval,
processed_dttm processed_dttm as &processed
from &ds1 from &ds1
where is_pk=1 where is_pk=1
order by key_hash, processed_dttm; order by &keyhash, &processed;
/* grab pk values */ /* grab pk values */
%local pk; %local pk;
data _null_; select distinct upcase(tgtvar_nm) into: pk separated by ' ' from &ds2;
set &ds2;
by key_hash;
call symputx('pk',catx(' ',symget('pk'),tgtvar_nm),'l');
if last.key_hash then stop;
run;
%let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_keychar)); %let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_keychar));
proc transpose data=&ds2(where=(tgtvar_type='C')) proc transpose data=&ds2(where=(tgtvar_type='C'))
out=&ds3(drop=_name_); out=&ds3(drop=_name_);
by KEY_HASH PROCESSED_DTTM; by &keyhash &processed;
id TGTVAR_NM; id TGTVAR_NM;
var charval; var charval;
run; run;
@@ -13513,7 +13516,7 @@ run;
%let ds4=%upcase(work.%mf_getuniquename(prefix=mpsd_keynum)); %let ds4=%upcase(work.%mf_getuniquename(prefix=mpsd_keynum));
proc transpose data=&ds2(where=(tgtvar_type='N')) proc transpose data=&ds2(where=(tgtvar_type='N'))
out=&ds4(drop=_name_); out=&ds4(drop=_name_);
by KEY_HASH PROCESSED_DTTM; by &keyhash &processed;
id TGTVAR_NM; id TGTVAR_NM;
var numval; var numval;
run; run;
@@ -13521,20 +13524,32 @@ run;
%mp_ds2squeeze(&ds3,outds=&ds3) %mp_ds2squeeze(&ds3,outds=&ds3)
%mp_ds2squeeze(&ds4,outds=&ds4) %mp_ds2squeeze(&ds4,outds=&ds4)
/* now merge to get all key values and de-dup */
%let ds5=%upcase(work.%mf_getuniquename(prefix=mpsd_merged)); %let ds5=%upcase(work.%mf_getuniquename(prefix=mpsd_merged));
data &ds5; data &ds5;
length key_hash $32 processed_dttm 8; length &keyhash $32 &processed 8;
merge &ds3 &ds4; merge &ds3 &ds4;
by key_hash; by &keyhash &processed;
if not missing(key_hash); if not missing(&keyhash);
run;
proc sort data=&ds5 nodupkey;
by &pk;
run; run;
/* join to base table for preliminary stage DS */ /* join to base table for preliminary stage DS */
proc sql; proc sql;
create table &outds as select "No " as _____DELETE__THIS__RECORD_____, create table &outds as select "No " as _____DELETE__THIS__RECORD_____
b.* %do x=1 %to %sysfunc(countw(&pk,%str( )));
,a.%scan(&pk,&x,%str( ))
%end;
%local notpkcols;
%let notpkcols=%upcase(%mf_getvarlist(&libds));
%let notpkcols=%mf_wordsinstr1butnotstr2(str1=&notpkcols,str2=&pk);
%do x=1 %to %sysfunc(countw(&notpkcols,%str( )));
,b.%scan(&notpkcols,&x,%str( ))
%end;
from &ds5 a from &ds5 a
inner join &libds b left join &libds (where=(&filterstr)) b
on 1=1 on 1=1
%do x=1 %to %sysfunc(countw(&pk,%str( ))); %do x=1 %to %sysfunc(countw(&pk,%str( )));
and a.%scan(&pk,&x,%str( ))=b.%scan(&pk,&x,%str( )) and a.%scan(&pk,&x,%str( ))=b.%scan(&pk,&x,%str( ))
@@ -13583,13 +13598,23 @@ data _null_;
end; end;
else if move_type='D' then do; else if move_type='D' then do;
if first.key_hash then do; if first.key_hash then do;
put "insert into &outds set _____DELETE__THIS__RECORD_____='No' " @@; put "update &outds set _____DELETE__THIS__RECORD_____='No' " @@;
end;
if IS_PK=0 then do;
put " ," tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end;
else do;
if first.is_pk then put " where 1=1 " @@;
put " and " tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end; end;
put " ," tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end; end;
if last.key_hash then put ';'; if last.key_hash then put ';';
run; run;

View File

@@ -22,6 +22,8 @@
change, plus ALL SUBSEQUENT CHANGES, will be reverted in the output table. change, plus ALL SUBSEQUENT CHANGES, will be reverted in the output table.
@param [in] difftable The dataset containing the diffs. Definition available @param [in] difftable The dataset containing the diffs. Definition available
in mddl_dc_difftable.sas in mddl_dc_difftable.sas
@param [in] filtervar= (0) If provided, the contents of this macro variable
will be applied as an additional filter against &libds
@param [out] outds= (work.mp_stripdiffs) Output table containing the diffs. @param [out] outds= (work.mp_stripdiffs) Output table containing the diffs.
Has the same format as the base datset, plus a Has the same format as the base datset, plus a
`_____DELETE__THIS__RECORD_____` variable. `_____DELETE__THIS__RECORD_____` variable.
@@ -30,7 +32,9 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarlist.sas
@li mf_islibds.sas @li mf_islibds.sas
@li mf_wordsinstr1butnotstr2.sas
@li mp_abort.sas @li mp_abort.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@@ -47,6 +51,7 @@
%macro mp_stripdiffs(libds %macro mp_stripdiffs(libds
,loadref ,loadref
,difftable ,difftable
,filtervar=0
,outds=work.mp_stripdiffs ,outds=work.mp_stripdiffs
,mdebug=0 ,mdebug=0
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -70,11 +75,11 @@
,msg=%str(Invalid library.dataset reference - %superq(libds)) ,msg=%str(Invalid library.dataset reference - %superq(libds))
) )
/* set up unique and temporary vars */ /* set up unique and temporary vars */
%local ds1 ds2 ds3 ds4 ds5 fref1; %local ds1 ds2 ds3 ds4 ds5 fref1 filterstr;
%let fref1=%mf_getuniquefileref(); %let fref1=%mf_getuniquefileref();
%if &filtervar ne 0 %then %let filterstr=%superq(&filtervar);
%else %let filterstr=%str(1=1);
/* get timestamp of the diff to be reverted */ /* get timestamp of the diff to be reverted */
%local ts; %local ts;
@@ -97,30 +102,28 @@ create table &ds1 (drop=libref dsn) as
/* extract key values only */ /* extract key values only */
%let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_pks)); %let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_pks));
%local keyhash processed;
%let keyhash=%upcase(%mf_getuniquename(prefix=mpsdvar_keyhash));
%let processed=%upcase(%mf_getuniquename(prefix=mpsdvar_processed));
create table &ds2 as create table &ds2 as
select key_hash, select key_hash as &keyhash,
tgtvar_nm, tgtvar_nm,
tgtvar_type, tgtvar_type,
coalescec(oldval_char,newval_char) as charval, coalescec(oldval_char,newval_char) as charval,
coalesce(oldval_num, newval_num) as numval, coalesce(oldval_num, newval_num) as numval,
processed_dttm processed_dttm as &processed
from &ds1 from &ds1
where is_pk=1 where is_pk=1
order by key_hash, processed_dttm; order by &keyhash, &processed;
/* grab pk values */ /* grab pk values */
%local pk; %local pk;
data _null_; select distinct upcase(tgtvar_nm) into: pk separated by ' ' from &ds2;
set &ds2;
by key_hash;
call symputx('pk',catx(' ',symget('pk'),tgtvar_nm),'l');
if last.key_hash then stop;
run;
%let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_keychar)); %let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_keychar));
proc transpose data=&ds2(where=(tgtvar_type='C')) proc transpose data=&ds2(where=(tgtvar_type='C'))
out=&ds3(drop=_name_); out=&ds3(drop=_name_);
by KEY_HASH PROCESSED_DTTM; by &keyhash &processed;
id TGTVAR_NM; id TGTVAR_NM;
var charval; var charval;
run; run;
@@ -128,7 +131,7 @@ run;
%let ds4=%upcase(work.%mf_getuniquename(prefix=mpsd_keynum)); %let ds4=%upcase(work.%mf_getuniquename(prefix=mpsd_keynum));
proc transpose data=&ds2(where=(tgtvar_type='N')) proc transpose data=&ds2(where=(tgtvar_type='N'))
out=&ds4(drop=_name_); out=&ds4(drop=_name_);
by KEY_HASH PROCESSED_DTTM; by &keyhash &processed;
id TGTVAR_NM; id TGTVAR_NM;
var numval; var numval;
run; run;
@@ -136,20 +139,32 @@ run;
%mp_ds2squeeze(&ds3,outds=&ds3) %mp_ds2squeeze(&ds3,outds=&ds3)
%mp_ds2squeeze(&ds4,outds=&ds4) %mp_ds2squeeze(&ds4,outds=&ds4)
/* now merge to get all key values and de-dup */
%let ds5=%upcase(work.%mf_getuniquename(prefix=mpsd_merged)); %let ds5=%upcase(work.%mf_getuniquename(prefix=mpsd_merged));
data &ds5; data &ds5;
length key_hash $32 processed_dttm 8; length &keyhash $32 &processed 8;
merge &ds3 &ds4; merge &ds3 &ds4;
by key_hash; by &keyhash &processed;
if not missing(key_hash); if not missing(&keyhash);
run;
proc sort data=&ds5 nodupkey;
by &pk;
run; run;
/* join to base table for preliminary stage DS */ /* join to base table for preliminary stage DS */
proc sql; proc sql;
create table &outds as select "No " as _____DELETE__THIS__RECORD_____, create table &outds as select "No " as _____DELETE__THIS__RECORD_____
b.* %do x=1 %to %sysfunc(countw(&pk,%str( )));
,a.%scan(&pk,&x,%str( ))
%end;
%local notpkcols;
%let notpkcols=%upcase(%mf_getvarlist(&libds));
%let notpkcols=%mf_wordsinstr1butnotstr2(str1=&notpkcols,str2=&pk);
%do x=1 %to %sysfunc(countw(&notpkcols,%str( )));
,b.%scan(&notpkcols,&x,%str( ))
%end;
from &ds5 a from &ds5 a
inner join &libds b left join &libds (where=(&filterstr)) b
on 1=1 on 1=1
%do x=1 %to %sysfunc(countw(&pk,%str( ))); %do x=1 %to %sysfunc(countw(&pk,%str( )));
and a.%scan(&pk,&x,%str( ))=b.%scan(&pk,&x,%str( )) and a.%scan(&pk,&x,%str( ))=b.%scan(&pk,&x,%str( ))
@@ -198,13 +213,23 @@ data _null_;
end; end;
else if move_type='D' then do; else if move_type='D' then do;
if first.key_hash then do; if first.key_hash then do;
put "insert into &outds set _____DELETE__THIS__RECORD_____='No' " @@; put "update &outds set _____DELETE__THIS__RECORD_____='No' " @@;
end;
if IS_PK=0 then do;
put " ," tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end;
else do;
if first.is_pk then put " where 1=1 " @@;
put " and " tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end; end;
put " ," tgtvar_nm '=' @@;
cnt=count(oldval_char,'"');
charval=quote(trim(substr(oldval_char,1,32765-cnt)));
if tgtvar_type='C' then put charval @@;
else put oldval_num @@;
end; end;
if last.key_hash then put ';'; if last.key_hash then put ';';
run; run;