BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.

I should transform a proc sql join into a hash, but I'm having trouble because I don't know how to define the "DefineKey" since there are various operations, not a single key to define.
this is the example:

 

data RUOLO_DANNI;
input cod_source:$2. cod_anagrafico:$9. ts_inizio_validita:datetime20.  ts_fine_validita:datetime20.;
datalines;
1 A 02JAN2015:00:00:00 01JAN5999:00:00:00
5 B 17MAY2017:00:00:00 01JAN5999:00:00:00
5 C 09JAN2022:00:00:00 01JAN5999:00:00:00
;



data T_A_SOGGETTI_DN;
input cod_source:$2. cod_anagrafico:$9. cod_anagrafico_edwh:$20. ts_inizio_validita:datetime20.  ts_fine_validita:datetime20.;
datalines;
1 A AAA 02JAN2015:00:00:00 01JAN5999:00:00:00
;


   proc sql noprint;
   create table ruolo_danni_NEW
   as select RU.*
			,SO.cod_anagrafico_EDWH
  from      RUOLO_DANNI RU

   left join   T_A_SOGGETTI_DN SO
   on        
             RU.cod_anagrafico = SO.cod_anagrafico
             and ru.ts_inizio_validita between so.ts_inizio_validita and so.ts_fine_validita
             and compress(SO.cod_source)='1';
quit;

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

Then it should be

data ruolo_danni_NEW;
set ruolo_danni;
if _n_ = 1
then do;
  length ts_inizio_validita ts_fine_validita 8;
  declare hash so (dataset:"ta_soggetti_dn (where=(compress(cod_source)='1'))");
  so.definekey("cod_anagrafico");
  so.definedata("ts_inizio_validita","ts_fine_validita");
  so.definedone();
  call missing(ts_inizio_validita,ts_fine_validita);
end;
rc = so.find();
if rc = 0 and ts_inizio_validita le  ts_inizio_validita le ts_fine_validita;
drop rc ts_inizio_validita ts_fine_validita;
run;
Spoiler
Spoiler
 

View solution in original post

9 REPLIES 9
mariopellegrini
Pyrite | Level 9

no because there is also cod_source

Kurt_Bremser
Super User

But you don't use that in your ON condition in the SQL? This would mean that you may get multiple observations in your SQL for a single obs in the "left" dataset.

mariopellegrini
Pyrite | Level 9

no because there is the final expression and compress(SO.cod_source)='1', so you only take the cod_source = '1'

Kurt_Bremser
Super User

Then it should be

data ruolo_danni_NEW;
set ruolo_danni;
if _n_ = 1
then do;
  length ts_inizio_validita ts_fine_validita 8;
  declare hash so (dataset:"ta_soggetti_dn (where=(compress(cod_source)='1'))");
  so.definekey("cod_anagrafico");
  so.definedata("ts_inizio_validita","ts_fine_validita");
  so.definedone();
  call missing(ts_inizio_validita,ts_fine_validita);
end;
rc = so.find();
if rc = 0 and ts_inizio_validita le  ts_inizio_validita le ts_fine_validita;
drop rc ts_inizio_validita ts_fine_validita;
run;
Spoiler
Spoiler
 
mariopellegrini
Pyrite | Level 9

thanks Kurt_Bremser. for completeness I report the final code to obtain the same result of the proc sql;

 

data ruolo_danni_HASH;
set ruolo_danni;
if _n_ = 1
then do;
  length ts_inizio_validita ts_fine_validita 8;
  length cod_anagrafico_edwh $20.;
  declare hash so (dataset:"t_a_soggetti_dn (where=(compress(cod_source)='1'))");
  so.definekey("cod_anagrafico");
  so.definedata("cod_anagrafico_edwh","ts_inizio_validita","ts_fine_validita");
  so.definedone();
  call missing(cod_anagrafico_edwh, ts_inizio_validita,ts_fine_validita);
end;
rc = so.find();
if rc >= 0 and ts_inizio_validita le  ts_inizio_validita le ts_fine_validita;
drop rc ;
run;
mariopellegrini
Pyrite | Level 9

Kurt  I found some data inconsistencies between sql and hash, because the "ON" condition is different: ts_start_validation is taken from the left dataset, while ts_start_validation  ts_end_validation of the "beetween" are taken from the right dataset. This example explains the problem with a particular case ((the results of ruolo_danni_sql and ruolo_danni_hash are different):

data RUOLO_DANNI;
input cod_source:$2. cod_anagrafico:$9. ts_inizio_validita:datetime20.;
datalines;
1 21278 02JUL11:03:25:44
1 21278 02JUL11:03:25:45
1 21278 02JUL11:03:25:46
;
data T_A_SOGGETTI_DN;
input cod_source:$2. cod_anagrafico:$9. cod_anagrafico_edwh:$20. ts_inizio_validita:datetime20.  ts_fine_validita:datetime20.;
datalines;
1 21278 F_SCDDNL64D45Z133D 01JUL2011:11:15:02 01JUL2011:11:15:01
;
proc sql noprint;
create table ruolo_danni_sql as 
select RU.cod_anagrafico,
       RU.ts_inizio_validita,
	   RU.cod_source,
	   SO.cod_anagrafico_edwh
from RUOLO_DANNI RU
left join   T_A_SOGGETTI_DN SO
on      RU.cod_anagrafico = SO.cod_anagrafico
    and ru.ts_inizio_validita between so.ts_inizio_validita and so.ts_fine_validita
    and compress(SO.cod_source)='1';
quit;
data ruolo_danni_HASH;
set ruolo_danni;
if _n_ = 1
then do;
  length ts_inizio_validita ts_fine_validita 8;
  length cod_anagrafico_edwh $20.;
  declare hash so (dataset:"t_a_soggetti_dn (where=(compress(cod_source)='1'))");
  so.definekey("cod_anagrafico");
  so.definedata("cod_anagrafico_edwh","ts_inizio_validita","ts_fine_validita");
  so.definedone();
  call missing(cod_anagrafico_edwh, ts_inizio_validita,ts_fine_validita);
end;
rc = so.find();
if rc >= 0 and ts_inizio_validita le ts_inizio_validita le ts_fine_validita;
drop rc ;
run;

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 9 replies
  • 1909 views
  • 3 likes
  • 2 in conversation