З належною повагою до всіх і в ІМХО,
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.
Також у таблиці має бути два стовпці дати
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