SQL Server结果所有可能的排序

时间:2018-10-21 15:15:40

标签: sql sql-server recursion sql-order-by

我是这个论坛的新手,正在寻求有关以下问题的帮助。 我希望从结果集中获得所有可能的排序。 例如

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 :(得分:0)

我认为这是一个非常困难的问题。我的解决方案使用两个递归CTES:

Sub Loop_Example()
    Dim Firstrow As Long, Lastrow As Long, Lrow As Long
    Dim CalcMode As Long, ViewMode As Long
    With Application
        CalcMode = .Calculation
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
    End With
    With ActiveSheet
        .Select 'select sheet so we can change the window view
        ViewMode = ActiveWindow.View 'go to normal view, for speed
        ActiveWindow.View = xlNormalView
        .DisplayPageBreaks = False 'Turn off Page Breaks
        Firstrow = .UsedRange.Cells(1).Row  'Set first & last row
        Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
        For Lrow = Lastrow To Firstrow Step -1  'loop bottom to top
            With .Cells(Lrow, "A")
                If Not IsError(.Value) Then
                    Select Case .Value
                        Case Is <> "jelle", "ron", "dave": .EntireRow.Delete
                    End Select
                End If
            End With
        Next Lrow
    End With
    ActiveWindow.View = ViewMode
    With Application
        .ScreenUpdating = True
        .Calculation = CalcMode
    End With
End Sub

(当然,逗号是值的任意定界符。如果值已经有逗号,则可以将其更改为所需的任何内容)。

第一个递归cte(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实际上是具有完整组合(在这种情况下,长度为3)的cte。您可能会发现orderings具有您要查找的信息。

然后,第二个递归cte(orderings)扩展拆分以使结果返回到行中。

这是一个有趣的练习,但是我不会在只有几行的表上运行这样的代码。输出行数为n * n! (n阶乘)。增长非常快。

我还应该指出,这种逻辑可能更适合在应用程序级别而不是SQL中实现。但这是一个有趣的SQL问题。毕竟,解决方案为n * n的问题并不多!原始表中的行。

答案 1 :(得分:0)

鉴于预期的结果,这是一个奇怪的挑战。

但是您可以通过自我联接来实现。
可用于查找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;