Můžete použít rekurzivní faktoring poddotazů (také známé jako rekurzivní 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
Je to v podstatě procházení vašich manuálních kroků. Kotevní člen je váš první ruční krok, nastavení x
a y
obě na nulu pro první řadu. Rekurzivní člen pak provede vámi zadaný výpočet. (Nemůžete odkazovat na nově vypočítaný x
hodnotu při výpočtu y
daného řádku , takže to musíte zopakovat jako (tmp.n * 2) + r.y - 1
). rn
slouží pouze k udržení pořadí řádků podle ID a zároveň usnadňuje nalezení dalšího řádku – můžete tedy hledat rn + 1
místo přímého hledání další nejvyšší hodnoty ID.
S vašimi ukázkovými daty není žádný významný rozdíl ve výkonu, ale s tisíci přidanými řádky trvá modelová klauzule asi 5 sekund a rekurzivní CTE asi 1 sekundu; s dalšími tisíci řádky model trvá ~20 sekund a CTE trvá ~3 sekundy; s dalším tisíci řádky model trval ~40 sekund a CTE trvalo ~6 sekund; a s dalšími tisíci řádky (takže celkem 4 008) model trval ~75 sekund a CTE ~10 sekund. (Znudilo mě čekání na modelovou verzi s více řadami, zabil jsem to po pěti minutách s 10 000). Nedokážu přesně říct, jak to bude fungovat s vašimi skutečnými daty, ale na základě toho to pravděpodobně stojí za pokus.