С уважением ко всем и в ИМХО
There is not much difference between While LOOP and Recursive CTE in terms of RBAR
При использовании не так много прироста Recursive CTEи Window Partition functionвсе в одном.
Appidдолжно быть int identity(1,1), или это должно быть постоянно увеличивается clustered index.
Помимо других преимуществ это также гарантирует, что все последующие ряды APPDateэтого пациента должны быть больше.
Таким образом, вы можете легко поиграть APPIDв своем запросе, что будет более эффективно, чем помещать inequalityоператоры типа>, <в APPDate. Помещение inequalityоператора как>, <в APPID поможет Sql Optimizer.
Также в таблице должно быть два столбца даты
APPDateTime datetime2(0) not null,
Appdate date not null
Так как это самые важные столбцы в самой важной таблице, поэтому не так много приведено.
Так Non clustered indexможет быть создано на Appdate
Create NonClustered index ix_PID_AppDate_App on APP (patientid,APPDate) include(other column which is not i predicate except APPID)
Протестируйте мой скрипт с другими примерами данных и узнайте, для каких примеров он не работает. Даже если это не сработает, я уверен, что это можно исправить в самой логике моего скрипта.
CREATE TABLE #Appt1 (ApptID INT, PatientID INT, ApptDate DATE)
INSERT INTO #Appt1
SELECT 1,101,'2020-01-05' UNION ALL
SELECT 2,505,'2020-01-06' UNION ALL
SELECT 3,505,'2020-01-10' UNION ALL
SELECT 4,505,'2020-01-20' UNION ALL
SELECT 5,101,'2020-01-25' UNION ALL
SELECT 6,101,'2020-02-12' UNION ALL
SELECT 7,101,'2020-02-20' UNION ALL
SELECT 8,101,'2020-03-30' UNION ALL
SELECT 9,303,'2020-01-28' UNION ALL
SELECT 10,303,'2020-02-02'
;With CTE as
(
select a1.* ,a2.ApptDate as NewApptDate
from #Appt1 a1
outer apply(select top 1 a2.ApptID ,a2.ApptDate
from #Appt1 A2
where a1.PatientID=a2.PatientID and a1.ApptID>a2.ApptID
and DATEDIFF(day,a2.ApptDate, a1.ApptDate)>30
order by a2.ApptID desc )A2
)
,CTE1 as
(
select a1.*, a2.ApptDate as FollowApptDate
from CTE A1
outer apply(select top 1 a2.ApptID ,a2.ApptDate
from #Appt1 A2
where a1.PatientID=a2.PatientID and a1.ApptID>a2.ApptID
and DATEDIFF(day,a2.ApptDate, a1.ApptDate)<=30
order by a2.ApptID desc )A2
)
select *
,case when FollowApptDate is null then 'New'
when NewApptDate is not null and FollowApptDate is not null
and DATEDIFF(day,NewApptDate, FollowApptDate)<=30 then 'New'
else 'Followup' end
as Category
from cte1 a1
order by a1.PatientID
drop table #Appt1