1. やりたい事
表題の通り、再帰WITH句で下記のような数値の順列(重複無し)を生成してみます。
1 ... 1
1, 2 ... 12, 21
1, 2, 3 ... 123, 132, 213, 231, 312, 321
:
nPr の公式で n = r の順列となります。使用するのは Oracle Database で
ちょっとした検証だったので Live SQL のサイトでガチャガチャと検証彡(゚)(゚)
Oracle Live SQL
https://livesql.oracle.com/
2. 順列を生成するSQL
以下のような SQL で対象の順列を生成できました。数値1桁まで対応します。
WITH nums AS (
SELECT LEVEL AS C0
FROM DUAL
CONNECT BY LEVEL <= 3
),
cte(c1, c2) AS (
SELECT nums.c0, TO_CHAR(nums.c0)
FROM nums
UNION ALL
SELECT c1
, c2 || nums.c0
FROM nums, cte
WHERE LENGTH(c2) < 3
AND cte.c2 NOT LIKE '%' || TO_CHAR(nums.c0) || '%'
)
SELECT *
FROM cte
WHERE LENGTH(c2) = 3
ORDER BY c2;
結果は以下の通り。n = r の順列の場合は n!(階乗) で要素数を表現できます。3 の場合は 321 で 6個
1,2,3,4,5 の順列では下記のようになります。要素数は 5!=54321 で 120個ですね。
3. SQLの解説
以下のような考え方で SQL を組んでいます。
・初めのWITH句(nums仮表)で順列の生成に必要な数値(1, 2, 3, ...)を生成しています。
・再帰WITH句の開始条件(開始レコード)はnums仮表の各要素
・再帰WITH句の継続条件は 長さが求める順列の長さより小さい場合 かつ nums仮表の要素を順列(c2列)に含まない場合
・そのままだと短い順列も取得されてしまうので、順列の文字列長で絞り込んでいます。
上記の通り再帰WITH句の継続条件の判定がショボいので、1桁の数値までしか対応しません。
4. 参考サイト
下記のサイトを参考にさせて頂きました。ありがとうございます!彡(^)(^)
SQL だけで再帰的に順列/組み合わせを列挙する
https://zenn.dev/indigo13love/articles/b04f8f2973fee3
上記サイトのように配列型を定義してゴニョゴニョすれば、1桁制限も突破できるとは思われる。
彡(゚)(゚)