この SQL は、繰り返しなしで順列を計算します。
WITH recurse(Result, Depth) AS
(
SELECT CAST(Value AS VarChar(100)), 1
FROM MyTable
UNION ALL
SELECT CAST(r.Result + '+' + a.Value AS VarChar(100)), r.Depth + 1
FROM MyTable a
INNER JOIN recurse r
ON CHARINDEX(a.Value, r.Result) = 0
)
SELECT Result
FROM recurse
WHERE Depth = (SELECT COUNT(*) FROM MyTable)
ORDER BY Result
9 行が含まれている場合MyTable
、計算に時間がかかりますが、362,880 行が返されます。
説明付きで更新:
このWITH
ステートメントは、再帰的な共通テーブル式を定義するために使用されます。実際には、ステートメントは、再帰が終了WITH
するまで a を実行して複数回ループしています。UNION
SQL の最初の部分は、開始レコードを設定します。に「A」、「B」、「C」という名前の 3 つの行があると仮定すると、MyTable
次の行が生成されます。
Result Depth
------ -----
A 1
B 1
C 1
次に、SQL の次のブロックが最初のレベルの再帰を実行します。
SELECT CAST(r.Result + '+' + a.Value AS VarChar(100)), r.Depth + 1
FROM MyTable a
INNER JOIN recurse r
ON CHARINDEX(a.Value, r.Result) = 0
これにより、これまでに生成されたすべてのレコード (recurse
テーブルに表示されます) が取得され、それらが再びすべてのレコードに結合されMyTable
ます。このON
句は、レコードのリストをフィルタリングしMyTable
て、この行の順列にまだ存在しないレコードのみを返します。これにより、次の行が生成されます。
Result Depth
------ -----
A 1
B 1
C 1
A+B 2
A+C 2
B+A 2
B+C 2
C+A 2
C+B 2
次に、再帰ループが再び繰り返され、次の行が返されます。
Result Depth
------ -----
A 1
B 1
C 1
A+B 2
A+C 2
B+A 2
B+C 2
C+A 2
C+B 2
A+B+C 3
A+C+B 3
B+A+C 3
B+C+A 3
C+A+B 3
C+B+A 3
この時点で、は常に であるUNION
ため、 はこれ以上行を作成しないため、再帰は停止します。CHARINDEX
0
Depth
最後の SQL は、計算列が のレコード数と一致するすべての結果行をフィルター処理しますMyTable
。これにより、再帰の最後の深さによって生成された行を除くすべての行が破棄されます。したがって、最終結果は次の行になります。
Result
------
A+B+C
A+C+B
B+A+C
B+C+A
C+A+B
C+B+A