次の形式の PostgreSQL テーブルがあります。
base_id int | mods smallint[]
3 | {7,15,48}
次の形式のテーブルにデータを入力する必要があります。
combo_id int | base_id int | mods smallint[]
1 | 3 |
2 | 3 | {7}
3 | 3 | {7,15}
4 | 3 | {7,48}
5 | 3 | {7,15,48}
6 | 3 | {15}
7 | 3 | {15,48}
8 | 3 | {48}
最初のテーブルを反復処理し、組み合わせを 2 番目のテーブルに書き込む関数を使用して、これをほぼ正確に行うことができると思います: SQL ですべての組み合わせを生成する
しかし、私はPostgresの初心者であり、plpgsqlを使用してこれを行う方法を一生理解できません。特に高速である必要はありません。バックエンドで定期的にのみ実行されます。最初のテーブルには約 80 のレコードがあり、大まかな計算では、2 番目のテーブルには約 2600 のレコードが期待できることを示唆しています。
誰かが少なくとも私を正しい方向に向けることができますか?
編集: Craig: PostgreSQL 9.0 を持っています。UNNEST() を正常に使用できました。
FOR messvar IN SELECT * FROM UNNEST(mods) AS mod WHERE mod BETWEEN 0 AND POWER(2, @n) - 1
LOOP
RAISE NOTICE '%', messvar;
END LOOP;
しかし、次にどこに行くべきかわかりませんでした。
編集:参考までに、私は最終的にErwinのソリューションを使用し、各セットにnull結果(「{}」)を追加するために1行追加し、Erwinが参照する特別なケースを削除しました:
CREATE OR REPLACE FUNCTION f_combos(_arr integer[], _a integer[] DEFAULT '{}'::integer[], _z integer[] DEFAULT '{}'::integer[])
RETURNS SETOF integer[] LANGUAGE plpgsql AS
$BODY$
DECLARE
i int;
j int;
_up int;
BEGIN
IF array_length(_arr,1) > 0 THEN
_up := array_upper(_arr, 1);
IF _a = '{}' AND _z = '{}' THEN RETURN QUERY SELECT '{}'::int[]; END IF;
FOR i IN array_lower(_arr, 1) .. _up LOOP
FOR j IN i .. _up LOOP
CASE j-i
WHEN 0,1 THEN
RETURN NEXT _a || _arr[i:j] || _z;
ELSE
RETURN NEXT _a || _arr[i:i] || _arr[j:j] || _z;
RETURN QUERY SELECT *
FROM f_combos(_arr[i+1:j-1], _a || _arr[i], _arr[j] || _z);
END CASE;
END LOOP;
END LOOP;
ELSE
RETURN NEXT _arr;
END IF;
END;
$BODY$
次に、その関数を使用してテーブルにデータを入力しました。
INSERT INTO e_ecosystem_modified (ide_ecosystem, modifiers)
(SELECT ide_ecosystem, f_combos(modifiers) AS modifiers FROM e_ecosystem WHERE ecosystemgroup <> 'modifier' ORDER BY ide_ecosystem, modifiers);
ソース テーブルの 79 行と修飾子配列の最大 7 項目から、クエリは出力テーブルに 2630 行を入力するのに 250 ミリ秒かかりました。素晴らしい。