Это действительно сложная проблема, на мой взгляд.Мое решение использует два рекурсивных 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!строки из исходной таблицы.