在我看来,这是一个非常困难的问题。我的解决方案使用两个递归 CTES:
with t as (select * from (values ('a'), ('b'), ('c')) v(col)),
tn as (
select row_number() over (order by col) as n, col
from t
),
cte as (
select ',' + cast(n as varchar(max)) + ',' as ordering,
cast(col as varchar(max)) + ',' as columns,
1 as lev
from tn
union all
select cte.ordering+ cast(tn.n as varchar(max)) + ',' ,
cast(cte.columns + tn.col as varchar(max)) + ',',
lev + 1
from cte join
tn
on cte.ordering not like '%,' + cast(tn.n as varchar(max)) + ',%'
),
orderings as (
select top (1) with ties cte.*
from cte
order by lev desc
),
splits as (
select ordering, columns,
left(columns, charindex(',', columns) - 1) as val,
stuff(columns, 1, charindex(',', columns) , '') as rest,
1 as lev
from orderings
union all
select ordering, columns,
left(rest, charindex(',', rest) - 1) as val,
stuff(rest, 1, charindex(',', rest), '') as rest,
lev + 1
from splits
where rest like '%,%'
)
select *
from splits;
order by ordering, lev;
(当然,逗号是值的任意分隔符。如果值可能已经有逗号,您可以将其更改为任何您想要的)。
第一个递归 cte (cte) 计算所有可能的排序 - 但每个排序只有一行。它遍历数据,构建所有可能的组合,一次一个元素。 cte orderings 实际上是具有完整组合的 cte(在这种情况下长度为 3)。您可能会发现orderings 有您要查找的信息。
第二个递归 cte (splits) 然后扩展拆分以将结果返回到行中。
这是一个有趣的练习,但我不会在一个多于几行的表上运行这样的代码。输出行数为 n * n! (n 阶乘)。这增长得相当快。
我还应该指出,这种类型的逻辑可能更适合在应用程序级别实现,而不是在 SQL 中。但这是一个有趣的 SQL 问题。毕竟解为n * n的问题并不多!原始表中的行。