SQL Server Результаты всех возможных упорядочений - PullRequest
0 голосов
/ 21 октября 2018

Я новичок в этом форуме и ищу помощи по следующей проблеме.Я ищу, чтобы получить все возможные заказы из набора результатов.например,

Column1
-------
val1
val2
val3

Ожидаемый результат

RowNumCoumn   Column1
-----------   -------
1              Val1         
2              Val2
3              Val3
4              Val1
5              Val3
6              Val2
7              Val2
8              Val1
9              Val3
10             Val2
11             Val3
12             Val1
13             Val3
14             Val1
15             Val2
16             Val3
17             Val2
18             Val1

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

Немного странный вызов, учитывая ожидаемые результаты.

Но вы можете сделать это через самостоятельные соединения.
С помощью которых можно найти все комбинации из 3 значений.

Затем откройте этот результат, чтобы получить ожидаемый результат.

Пример фрагмента:

declare @Table table (Column1 varchar(30));

insert into @Table (Column1) values
('val1'),
('val2'),
('val3');

select 
row_number() over (order by rn, Col) as RowNumColumn,
Val as Column1
from
(
    select 
    t1.Column1 as Col1, 
    t2.Column1 as Col2, 
    t3.Column1 as Col3,
    row_number() over (order by t1.Column1, t2.Column1, t3.Column1) as rn
    from @Table as t1
    left join @Table as t2 on t2.Column1 != t1.Column1
    left join @Table as t3 on t3.Column1 not in (t1.Column1, t2.Column1)
) src
UNPIVOT (
    Val 
    FOR Col IN ([Col1], [Col2], [Col3])
) as unpvt
order by RowNumColumn;
0 голосов
/ 21 октября 2018

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

...