BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Cugel
Obsidian | Level 7


Hello who can help me with a loop function that runs through the days between a start date and an end date.

I am a beginner(newbee) in SAS proc SQL so please provide clear instructions

I work with a hospital admission table in which per patient a start date of the admission and the end date of the admission is stated.
Now I am looking for a loop function that runs through the day of the hospital admission.

The output is then used for further calculations and linking to other tables such as pain measurements per day.

Hopefully my question is clear and someone can help me. SAS DI version 4.903

 

Screen Shot 07-25-19 at 02.07 PM.JPG

1 ACCEPTED SOLUTION

Accepted Solutions
Cugel
Obsidian | Level 7

Hello Kurt

Your solution works like a train. Had to make a small adjustment in case the clinic start_admission_date and the clinic

end _admission_date fall on the same day. Patient stays in the hospital for only a few hours.

Maybe you have a smarter solution than my adjustment. Thank you for the suggested solution.

 

data want;
set have (rename=(end_date_admission=end_date));
if end_date = . then end_date = datetime();
day_date = datepart(start_date_admission);

if datepart(d_opn) ne datepart(end_date) then

do until (day_date >= datepart(end_date));
  end_date_admission = intnx('dtday',start_date_admission,1,'b');
  duration = intck('minute',start_date_admission,end_date_admission);
  output;
  day_date = day_date + 1;
  start_date_admission = end_date_admission;
end;

;
end_date_admission = end_date;
duration = intck('minute',start_date_admission,end_date_admission);
output;
drop end_date;
run;

View solution in original post

12 REPLIES 12
Kurt_Bremser
Super User

A simple do loop:

data want;
set have (rename=(end_date_admission=end_date));
if end_date = . then end_date = datetime();
day_date = datepart(start_date_admission);
do until (day_date >= datepart(end_date));
  end_date_admission = intnx('dtday',start_date_admission,1,'b');
  duration = intck('minute',,start_date_admission,end_date_admission);
  output;
  day_date = day_date + 1;
  start_date_admission = end_date_admission;
end;
end_date_admission = end_date;
duration = intck('minute',start_date_admission,end_date_admission);
output;
drop end_date;
run;

Untested, for lack of usable data.

 

Please post example data in a data step with datalines, so we can easily recreate your dataset(s) with a copy/paste and submit. Nobody here is keen on tediously typing data off a picture. Help us to help you.

Cugel
Obsidian | Level 7

Hello Kurt

Your solution works like a train. Had to make a small adjustment in case the clinic start_admission_date and the clinic

end _admission_date fall on the same day. Patient stays in the hospital for only a few hours.

Maybe you have a smarter solution than my adjustment. Thank you for the suggested solution.

 

data want;
set have (rename=(end_date_admission=end_date));
if end_date = . then end_date = datetime();
day_date = datepart(start_date_admission);

if datepart(d_opn) ne datepart(end_date) then

do until (day_date >= datepart(end_date));
  end_date_admission = intnx('dtday',start_date_admission,1,'b');
  duration = intck('minute',start_date_admission,end_date_admission);
  output;
  day_date = day_date + 1;
  start_date_admission = end_date_admission;
end;

;
end_date_admission = end_date;
duration = intck('minute',start_date_admission,end_date_admission);
output;
drop end_date;
run;

Kurt_Bremser
Super User

Given your variable names, the condition should be

if datepart(start_date_admission) ne datepart(end_date) then

Otherwise, it solves the problem of one-day stays very nicely.

Cugel
Obsidian | Level 7
Hello Kurt, thank you very much for your input.

However, the final solution is not yet clear.

I now have insight into the days within the hospitalization period.

But the next problem is that a patient may have been in multiple nursing units on one calendar day.

I will compile a dataset that makes that clear.

To be continued.
Cugel
Obsidian | Level 7

Hello Kurt,

 

Your proc sql procedure works well.

But I have an additional question.

The output of the procedure is written to an Oracle table, but now Oracle does not correctly process the format of the "day_date" field.

Is it possible to make the field "day_date" a datetime20. format?

 

Thanks in advance for your response.

Kurt_Bremser
Super User

To convert a date to a datetime value, do

day_date = dhms(day_date,0,0,0);
format day_date datetime20.;

or in SQL

dhms(day_date,0,0,0) format=datetime20. as day_date
Cugel
Obsidian | Level 7
Hello Kert,
Thanks the suggested solution works. I have not yet tested it in the proc sql procedure. The adjustment below gave the desired result.
[cid:image001.png@01D579F3.2DA30590]
Cugel
Obsidian | Level 7

Hello Kurt,

May I again appeal to you for your SAS knowledge.

In nursing, we use three daily rosters for the nurses.

Now we would like to split the length of stay on the ward per calendar day into the duration of stay per roster.

This is quite a puzzle since the length of stay can start in roster1 and end in roster2 or start in roster1 and also end in roster1 etc. etc..

Maybe you have a suggestion, idea or solution.

Thanks in advance for your response.

 

Roster1 23:30 until 07:30 (>23:30 <=07:30) (duration 8 hours --> 30 minutes until midnight and 450 minutes until start roster2) 

Roster2 07:30 until 15:30 (>07:30 <=15:30)  (duration 8 hours)

Roster3 15:30 until 23:30 (>15:30 <=23:30)  (duration 8 hours)

 

data_input

data_input.JPG

desired output

desirable_output.JPG

ballardw
Super User

Standard SQL does not have a Do loop construct.

LinusH
Tourmaline | Level 20

My take on this would be joining with a date/time dimension using a BETWEEN AND join criteria.

Thus avoiding using User Written code.

Data never sleeps
Cugel
Obsidian | Level 7

Hello Linus, As a learning newbee, I also looked at your proposed solution.

Unfortunately it is unclear to me how a join can make the intervening records visible between the start_admission_date and the end_admission_date. I have a dim_date table. Maybe you can explain the join statement.

 

 

INPUT FROM Oracle TABLE "ADMISSION"

PATIENT_IDADMISSION_IDSTART_DATE_ADMISSIONEND_DATE_ADMISSION
19955782369264015-07-2019 00:0118-07-2019 11:08
13787632369264215-07-2019 00:2515-07-2019 10:15
14384682369266115-07-2019 02:48.
16556502369266215-07-2019 05:43.
24735372369380115-07-2019 13:4018-07-2019 14:57
14335122369400315-07-2019 14:2322-07-2019 13:15

 

Records for July 2019 in the dim_date table.

SK_DIM_DATEDATE9DDMMYYD10DATE_CHAR
4364601JUL2019:00:00:0001-07-201901-jul-19
4364702JUL2019:00:00:0002-07-201902-jul-19
4364803JUL2019:00:00:0003-07-201903-jul-19
4364904JUL2019:00:00:0004-07-201904-jul-19
4365005JUL2019:00:00:0005-07-201905-jul-19
4365106JUL2019:00:00:0006-07-201906-jul-19
4365207JUL2019:00:00:0007-07-201907-jul-19
4365308JUL2019:00:00:0008-07-201908-jul-19
4365409JUL2019:00:00:0009-07-201909-jul-19
4365510JUL2019:00:00:0010-07-201910-jul-19
4365611JUL2019:00:00:0011-07-201911-jul-19
4365712JUL2019:00:00:0012-07-201912-jul-19
4365813JUL2019:00:00:0013-07-201913-jul-19
4365914JUL2019:00:00:0014-07-201914-jul-19
4366015JUL2019:00:00:0015-07-201915-jul-19
4366116JUL2019:00:00:0016-07-201916-jul-19
4366217JUL2019:00:00:0017-07-201917-jul-19
4366318JUL2019:00:00:0018-07-201918-jul-19
4366419JUL2019:00:00:0019-07-201919-jul-19
4366520JUL2019:00:00:0020-07-201920-jul-19
4366621JUL2019:00:00:0021-07-201921-jul-19
4366722JUL2019:00:00:0022-07-201922-jul-19
4366823JUL2019:00:00:0023-07-201923-jul-19
4366924JUL2019:00:00:0024-07-201924-jul-19
4367025JUL2019:00:00:0025-07-201925-jul-19
4367126JUL2019:00:00:0026-07-201926-jul-19
4367227JUL2019:00:00:0027-07-201927-jul-19
4367328JUL2019:00:00:0028-07-201928-jul-19
4367429JUL2019:00:00:0029-07-201929-jul-19
4367530JUL2019:00:00:0030-07-201930-jul-19
4367631JUL2019:00:00:0031-07-201931-jul-19
Kurt_Bremser
Super User
proc sql;
create table want as
select
  a.patient_id,
  a.admission_id,
  b.date9
from admission a, dim_date b
where b.date9 between a.start_date_admission and a.end_date_admission
;
quit;

This is the code you need to achieve with the point-and-click interface, if you don't want to use a user written transformation in DI Studio.

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 12 replies
  • 3144 views
  • 3 likes
  • 4 in conversation