Sie könnten rekursive Unterabfragefaktorisierung verwenden (auch bekannt als rekursiver 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
Es geht im Grunde durch Ihre manuellen Schritte. Das Ankerelement ist Ihr erster manueller Schritt, indem Sie x
festlegen und y
beide auf Null für die erste Zeile. Das rekursive Mitglied führt dann die von Ihnen angegebene Berechnung durch. (Sie können nicht auf den neu berechneten x
verweisen -Wert bei der Berechnung von y
dieser Zeile , also müssen Sie das als (tmp.n * 2) + r.y - 1
wiederholen ). Der rn
dient nur dazu, die Zeilenreihenfolge nach ID beizubehalten und gleichzeitig das Auffinden der nächsten Zeile zu erleichtern - damit Sie nach rn + 1
suchen können anstatt direkt den nächsthöheren ID-Wert zu finden.
Es gibt keinen signifikanten Leistungsunterschied mit Ihren Beispieldaten, aber mit tausend hinzugefügten Zeilen dauert die Modellklausel etwa 5 Sekunden und der rekursive CTE etwa 1 Sekunde; mit weiteren tausend Zeilen dauert das Modell ca. 20 Sekunden und der CTE ca. 3 Sekunden; mit einem weiteren Modell mit tausend Zeilen dauerte es ~ 40 Sekunden und CTE dauerte ~ 6 Sekunden; und mit weiteren tausend Zeilen (also insgesamt 4.008) dauerte das Modell ~ 75 Sekunden und der CTE ~ 10 Sekunden. (Mir war langweilig, auf die Modellversion mit mehr Zeilen zu warten; ich habe sie nach fünf Minuten mit 10.000 getötet). Ich kann nicht wirklich sagen, wie sich das mit Ihren realen Daten verhält, aber auf dieser Grundlage ist es wahrscheinlich einen Versuch wert.