T-SQL中结果集的powerset(所有组合)

时间:2016-04-26 08:26:50

标签: sql-server tsql powerset

我需要一个t-sql代码来获取结果集的powerset。

示例输入:

ColumnName
1
2
3

Example Output(one columns as nvarchar) :
1
2
3
1,2
1,3
2,3
1,2,3

输出集可能包含重复值,例如(1,3 vs 3,1)。

2 个答案:

答案 0 :(得分:1)

您可以使用此功能并获得完整的功率设置。
享受它。

--EXEC PowerSet 'A,B,C,D'
Create PROCEDURE PowerSet(@Members NVARCHAR(64))
As
Begin
    Declare @SubSet NVARCHAR(Max),
            @SubSetCount int,
            @Counter1 int,
            @Counter2 int,
            @ID int
    Create table #Members
    (
        ID int IDENTITY(1,1) PRIMARY KEY,
        Member NVARCHAR(50)
    )
    Create table #PowerSets
    (
        SubSet NVARCHAR(50)
    )
    -- Start Convert @Members To Table #Members
    Set @Members=@Members+','
    While @Members<>''
    Begin
        Insert Into #Members(Member) 
        Values(Left(@Members,CHARINDEX(',',@Members)-1))
        Set @Members=RIGHT(@Members,LEN(@Members)-CHARINDEX(',',@Members))
    End
    -- End Convert @Members To Table #Members
    -- Start Calculat PowerSet
    Set @SubSetCount=POWER(2,(Select Count(*) From #Members))
    Set @Counter1=0
    while @Counter1<@SubSetCount
    Begin
        Set @Counter2=@Counter1
        Set @ID=1
        Set @SubSet='{'
        While @Counter2>0
        Begin
            If CONVERT(char(1), @Counter2 % 2)=1
                 Set @SubSet=@SubSet+iif(@SubSet<>'{',',','')+(Select Member From #Members Where ID=@ID)
            Set @Counter2 = CONVERT(int, (@Counter2 / 2))
            Set @ID=@ID+1
        End
        Set @Counter1=@Counter1+1
        Insert into #PowerSets(SubSet) values(@SubSet+'}')
    End
    -- End Calculat PowerSet
    Select *
    From #PowerSets
    Order By Len(SubSet),SubSet
    Drop Table #PowerSets
    Drop Table #Members 
End

答案 1 :(得分:0)

假设您想要获得名为@items 的表的幂集,其中包含一个名为 name 的列。你可以得到这样的powerset。根据需要更改表名、列名和列类型。如果您想将每个子集作为一行,那么只需在末尾按 sk.k 分组

declare @itemKeys table(
    Name varchar(255),
    K int
)
insert into @itemKeys(Name, K)
select Name, POWER(2,ROW_NUMBER()OVER(ORDER BY Name)-1)
from @items

declare @setKeys table(
    k int
)
insert into @setKeys(k)
select TOP(POWER(2,@n)) RANK()OVER(ORDER BY object_id)-1 as k
from sys.all_objects

select sk.K as SetKey, ik.Name
from @setKeys sk
join @itemKeys ik on ik.K & sk.K = ik.K
order by sk.K, ik.K