それを仮定すると...
-
gwma_duration
およびduration
同じ列であると想定されており、タイプミスのために異なります。 -
order_column
という名前の列で並べ替えます 。実際の列に置き換えてください。 -
主キー列は
res_id
です。 。実際の列に置き換えてください。
豚に口紅を塗る:
手続き型コードが修復および改善されました:
CREATE OR REPLACE FUNCTION vin_calc()
RETURNS void AS
$func$
DECLARE
r res%rowtype;
i integer := 0;
last_grp text;
BEGIN
FOR r IN
SELECT * FROM res
LOOP
IF last_grp <> r.prod_grp_nm THEN
i := 1;
ELSE
i := i + 1;
END IF;
IF i < 3 THEN
UPDATE res
SET duration = i - 1
WHERE dur = r.dur
AND prod_grp_nm = r.prod_grp_nm
AND week_end = r.week_end;
ELSE
UPDATE res r1
SET duration = r.dur * 0.125 +
(SELECT 0.875 * gwma_duration FROM res
WHERE order_column < r1.order_column
ORDER BY order_column
LIMIT 1
) -- could be replaced with last_duration, analog to last_grp
WHERE r1.dur = r.dur
AND r1.prod_grp_nm = r.prod_grp_nm
AND r1.week_end = r.week_end;
END IF;
last_grp := r.prod_grp_nm;
END LOOP;
END
$func$
LANGUAGE plpgsql;
-
<の暗黙カーソルを使用します。 code> FOR ループ 。扱いにくい明示カーソルは必要ありません。
-
言語名を引用しないでください
plpgsql
、これは文字列ではなく識別子です。 -
いくつかの場所でロジックを簡素化しました。
-
最も重要なこと 、エラーメッセージに示されているように、
SET
でウィンドウ関数を使用することはできません。UPDATE
の句 。相関サブクエリに置き換えました。ただし、おそらくlast_duration
に置き換えることができます。 、last_grp
に類似 :最後の反復の値を覚えておいてください。
適切なソリューション
ただし、単一の UPDATE
で実行できる場合、上記のすべては非常に非効率的です。 ステートメント :
UPDATE res r
SET duration = CASE WHEN r0.rn < 3
THEN r0.rn - 1
ELSE r0.last_dur * 0.875 + r.dur * 0.125
END
FROM (
SELECT res_id, duration
, row_number() OVER (PARTITION BY prod_grp_nm ORDER BY order_column) AS rn
, lag(duration) OVER (PARTITION BY prod_grp_nm ORDER BY order_column) AS last_dur
FROM res
) r0
WHERE r.res_id = r0.res_id
-
明確にするために:あなたはできます
FROM
でウィンドウ関数を使用する 条項-少なくとも現代版のPostgresでは。 -
row_number()
を使用します 、rank()
ではありません ストライク> 手続き型コードと同等になります。