Один способ использует lead()
и union all
:
select id, old_value, datediff(day, created, action_date) as days_in_stage
from t
where not exists (select 1
from t t2
where t2.id = t.id and t2.action_date < t.action_date
)
union all
select new_value,
date_diff(day,
action_date,
lead(action_date, 1, getdate()) over (partition by id order by action_date)
) as days_in_stage
from t;
Или более чистое решение (на мой взгляд) отменяет данные:
select t.id, v.value,
datediff(day,
coalesce(max(fromd), created),
coalesce(max(tod), getdate)
) as days_in_stage
from t cross apply
(values (t.old_value, t.action_date, null),
(t.new_value, null, t.action_date)
) v(value, tod, fromd)
group by t.id, v.value;