Можете да използвате факториране на рекурсивни подзаявки (известен също като рекурсивен CTE):
with tmp as (
select t.*,
row_number() over (order by t.id) as rn
from t
),
r (id, n, x, y, rn) as (
select id, n, 0, 0, rn
from tmp
where rn = 1
union all
select tmp.id, tmp.n, r.y - 1, (tmp.n * 2) + r.y - 1, tmp.rn
from r
join tmp on tmp.rn = r.rn + 1
)
select id, n, x, y
from r
order by rn;
ID N X Y
---------- ---------- ---------- ----------
2 0 0 0
3 1 -1 1
5 1 0 2
7 2 1 5
11 3 4 10
13 5 9 19
17 8 18 34
19 13 33 59
Това е основно преминаване през вашите ръчни стъпки. Закрепващият елемент е вашата първа ръчна стъпка, задаване на x
и y
и двете на нула за първия ред. След това рекурсивният член прави указаното от вас изчисление. (Не можете да се позовавате на новоизчисления x
стойност при изчисляване на y
на този ред , така че трябва да повторите това като (tmp.n * 2) + r.y - 1
). rn
е просто да запази редовете на редовете по ID, като същевременно улеснява намирането на следващия ред - така че можете да търсите rn + 1
вместо директно намиране на следващата най-висока стойност на ID.
Няма значителна разлика в производителността с вашите примерни данни, но с добавени хиляда реда моделната клауза отнема около 5 секунди, а рекурсивният CTE отнема около 1 секунда; с други хиляда реда моделът отнема ~20 секунди, а CTE отнема ~3 секунди; с други хиляда реда моделът отне ~40 секунди, а CTE отне ~6 секунди; и с още хиляда реда (т.е. общо 4008) моделът отне ~75 секунди, а CTE отне ~10 секунди. (Омръзна ми да чакам версията на модела с повече редове от това; убих го след пет минути с 10 000). Не мога наистина да кажа как ще се представи това с вашите реални данни, но на тази основа вероятно си струва да опитате.