Reputation: 89
I need to find all patients who have not had 3 visits within a 6 week period during a rolling year. I’ll start from a temp table that has all results for 1 year period, like this:
TempTable1
PatientName VisitDate
Steve 11/1/2016
Steve 11/2/2016
Steve 11/3/2016
Pete 11/1/2016
Pete 11/2/2016
Dave 2/3/2016
Dave 11/2/2016
Dave 2/2/2016
But I still need to
Select
PatientName
,/*most recent VisitDate*/
,ROW_NUMBER() OVER (Partition By PatientName ORDER BY VisitDate desc) AS RowNumber
FROM TempTable1
Where /*PatientName has <3 visits within any rolling 6 week period */
The result should be "Pete" and "Dave" since both do not have three visits within six week period. Steve does 3 visits within 6 weeks.
I could not find any good examples where they looked for more than once instance within a time frame. Thank you many times in advance. I'll be sure to leave great rating.
Upvotes: 0
Views: 79
Reputation: 11
This my proposition. Code is simple and is based on the fact 6 weeks=42 days. I hope that I helped
WITH TMP_CTE AS(
Select
PatientName,
VisitDate,
LEAD(VisitDate, 2) OVER(PARTITION BY PatientName ORDER BY VisitDate) AS OffsetVisitDate
DATEDIFF(day, VisitDate, LEAD(VisitDate, 2) OVER(PARTITION BY PatientName ORDER BY VisitDate)) as Difference_in_Days
FROM TempTable1
)
SELECT DISTINCT PatientName AS Patient_who_has_not_3visits
FROM TMP_CTE WHERE PatientName NOT IN
(
SELECT DISTINCT PatientName AS Patient_who_has_3visits_within_6week
FROM TMP_CTE
WHERE Difference_in_Days>42
)
Upvotes: 1
Reputation: 95082
A person got three visits within six weeks, when we find a visit where the previous visit and the following visit are no more than six weeks apart. We can use LAG
and LEAD
to find the previous and the following visits to a visit.
select patientname
from (select distinct patientname from temp) patients
where patientname not in
(
select patientname
from
(
select
patientname,
lag(visitdate) over (partition by patientname order by visitdate) as visit1,
lead(visitdate) over (partition by patientname order by visitdate) as visit3
from temp
) visits
where datediff(day, visit1, visit3) <= 42 -- 42 days = 6 weeks
);
Upvotes: 2
Reputation: 22811
Let's look at this from the other side. We'll check if minimum visit date within 3 preceding visits (current included) is within 6 weeks from current visit date.
with dat as (
-- sample data
select *
from (
values
('Steve',cast('11/1/2016' as date))
,('Steve',cast('11/2/2016' as date))
,('Steve',cast('11/3/2016' as date))
,('Pete ',cast('11/1/2016' as date))
,('Pete ',cast('11/2/2016' as date))
,('Dave ',cast('2/3/2016' as date))
,('Dave ',cast('11/2/2016' as date))
,('Dave ',cast('2/2/2016' as date))
)t(PatientName, VisitDate)
), cte as(
select PatientName
, md=datediff(week
,min(VisitDate) over(partition by PatientName order by VisitDate
rows between 2 preceding and current row)
,VisitDate)
, n = count(*) over(partition by PatientName order by VisitDate
rows between 2 preceding and current row)
from dat
)
select PatientName
from cte
group by PatientName
having max(n)<3 or max(md)>6
Upvotes: 1
Reputation: 1270773
This is challenging. I think that cross apply
might be the simplest method to implement:
select t.*, tt.numvisits
from temptable1 t cross apply
(select count(*) as numvisits
from temptable t2
where t2.patientname = t.patientname and
t2.visitdate >= t.visitdate and
t2.visitdate < dateadd(week, 6, t.visitdate)
) tt;
Then, if you want to find the people who don't have three visits:
select t.patientname
from temptable1 t cross apply
(select count(*) as numvisits
from temptable t2
where t2.patientname = t.patientname and
t2.visitdate >= t.visitdate and
t2.visitdate < dateadd(week, 6, t.visitdate)
) tt;
group by t.patientname
having max(numvisits) < 3;
Note that the cross apply
can take advantage of an index on temptable(patientdate, visitdate)
. If your data is not too big, then performance may even be reasonable.
Upvotes: 2