这个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
如果 MyTable
包含9行,计算需要一些时间,但会返回362,880行。
更新说明:
WITH
语句用于定义一个递归公共表达式。实际上,WITH
语句会执行多次 UNION
循环,直到递归结束。
SQL 的第一部分设置了起始记录。假设在 MyTable
中有3行,分别命名为'A'、'B'和'C',则将生成这些行:
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
。
最后一个SQL过滤掉所有计算出的Depth
列与MyTable
中记录数相匹配的结果行。这会剔除除了最后一层递归生成的行之外的所有行。因此,最终结果将是这些行:
Result
------
A+B+C
A+C+B
B+A+C
B+C+A
C+A+B
C+B+A