Вы можете использовать row_number()
:
select type, year(date), month(date),
(max(case when seqnum_desc = 1 then value end) -
max(case when seqnum_asc = 1 then value end)
) as month_diff
from (select t.*,
row_number() over (partition by type, year(date), month(date) order by date) as seqnum_asc,
row_number() over (partition by type, year(date), month(date) order by date desc) as seqnum_desc
from t
) t
group by type, year(date), month(date);
Если вы знаете, какие значения увеличиваются (или не уменьшаются), то вы можете использовать агрегирование:
select type, year(date), month(date), max(value) - min(value)
from t
group by type, year(date), month(date);