再帰的サブクエリファクタリング を使用できます。 (再帰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
SQLフィドル 。
それは基本的にあなたの手動のステップを歩いています。アンカーメンバーは、x
を設定する最初の手動ステップです。 およびy
最初の行は両方ともゼロになります。次に、再帰メンバーが指定した計算を実行します。 (新しく計算されたx
を参照することはできません その行のy
を計算するときの値 、したがって、(tmp.n * 2) + r.y - 1
として繰り返す必要があります。 )。 rn
次の行を見つけやすくしながら、IDで行の順序を維持するだけなので、rn + 1
を探すことができます。 次に高いID値を直接見つける代わりに。
サンプルデータとのパフォーマンスに大きな違いはありませんが、1,000行を追加すると、モデル句に約5秒かかり、再帰CTEに約1秒かかります。さらに1000行のモデルでは、約20秒かかり、CTEには約3秒かかります。さらに1000行のモデルでは、約40秒、CTEには約6秒かかりました。さらに1000行(合計4,008行)のモデルでは約75秒、CTEでは約10秒かかりました。 (私はそれよりも多くの行を持つモデルバージョンを待つのに飽きました; 10,000で5分後にそれを殺しました)。これが実際のデータでどのように機能するかはわかりませんが、それに基づいて、試してみる価値はあります。