Power Set

  • In:

    i

    -------

    1

    2

    3

    4

    Out:

    i

    -------

    1

    2

    3

    4

    1,2

    1,3

    1,4

    2,3

    2,4

    3,4

    1,2,3

    1,2,4

    1,3,4

    2,3,4

    1,2,3,4

    NULL

    /*--------

    declare @t table (i varchar(500), unique(i))

    insert @t select 1 union select 2 union select select 3 union select 4

    --------*/

  • Try this

    WITH RecCTE AS

    (

    SELECT Convert(VarChar(30),i) i FROM T

    UNION ALL

    SELECT Convert(Varchar(30),t2.i+','+t3.i) as i FROM T T2

    CROSS JOIN RecCTE T3

    WHERE t2.i<>t3.i AND t2.i<LEFT(t3.i,1)

    )

    SELECT * FROM RecCTE

    ORDER BY LEN(I),i

  • You probably wil have to use Paul White NZ's N-Way Handshaking code for your requirement!

    NOTE : Jeff Moden had advised that this code contains triangular joins and we must use this carefully or rather refrain from it!

    If it just a assignment,then this should work for you!

    The real code:

    DECLARE @People

    TABLE (

    person_id INTEGER IDENTITY(0,1) PRIMARY KEY,

    name VARCHAR(10) NOT NULL

    );

    INSERT @People (name) VALUES ('Alan');

    INSERT @People (name) VALUES ('Bob');

    INSERT @People (name) VALUES ('Carol');

    INSERT @People (name) VALUES ('Debra');

    INSERT @People (name) VALUES ('Eric');

    INSERT @People (name) VALUES ('Frank');

    INSERT @People (name) VALUES ('Gina');

    INSERT @People (name) VALUES ('Harry');

    INSERT @People (name) VALUES ('Ian');

    INSERT @People (name) VALUES ('Julie');

    DECLARE @Bits

    TABLE (

    bit_id BIGINT NOT NULL PRIMARY KEY,

    value BIGINT NOT NULL

    );

    INSERT @Bits (bit_id, value)

    SELECT P.person_id - 1, POWER(2, (P.person_id - 1))

    FROM @People P;

    DECLARE @Grouped

    TABLE (

    N BIGINT NOT NULL,

    name VARCHAR(10) NOT NULL,

    group_size BIGINT NOT NULL,

    group_order BIGINT NOT NULL,

    group_row BIGINT NOT NULL,

    UNIQUE (N, name),

    UNIQUE (group_row, group_size, group_order, N)

    );

    INSERT @Grouped

    (N, name, group_size, group_order, group_row)

    SELECT Q.N,

    Q.name,

    Q.group_size,

    group_order = DENSE_RANK() OVER (PARTITION BY Q.group_size ORDER BY Q.N),

    group_row = DENSE_RANK() OVER (PARTITION BY Q.group_size ORDER BY Q.name)

    FROM (

    SELECT N.N,

    P.name,

    group_size = COUNT(*) OVER (PARTITION BY N.N)

    FROM dbo.Numbers (POWER(2, (SELECT COUNT(*) FROM @People))) N

    JOIN @Bits B

    ON N.N & B.value = B.value

    JOIN @People P

    ON P.person_id = B.bit_id

    ) Q

    SELECT names =

    STUFF

    (

    (

    SELECT ',' + name

    FROM @Grouped T2

    WHERE T2.N = T1.N

    ORDER BY

    name ASC

    FOR XML PATH('')

    )

    , 1, 1, SPACE(0))

    FROM @Grouped T1

    WHERE group_row = 1

    ORDER BY

    T1.group_size,

    T1.group_order;

    GO

    The code for Numbers Function in that:

    DROP FUNCTION dbo.Numbers;

    GO

    CREATE FUNCTION dbo.Numbers

    (@N BIGINT)

    RETURNS TABLE

    WITH SCHEMABINDING

    AS RETURN

    WITH

    N1 AS (SELECT N = 1 UNION ALL SELECT 1),

    N2 AS (SELECT N = 1 FROM N1 T, N1),

    N3 AS (SELECT N = 1 FROM N2 T, N2),

    N4 AS (SELECT N = 1 FROM N3 T, N3),

    N5 AS (SELECT N = 1 FROM N4 T, N4),

    N6 AS (SELECT N = 1 FROM N5 T, N5),

    NM AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS N FROM N6)

    SELECT TOP (@N)

    N

    FROM NM

    WHERE N <= @N

    ORDER BY

    N ASC;

    GO

    Hope this helps you! But i am expecting Jeff to comment on this!

    😎

  • Good code , Gopi! 😎

  • Thank you:-)

  • ColdCoffee (5/18/2010)


    You probably wil have to use Paul White NZ's N-Way Handshaking code for your requirement!

    NOTE : Jeff Moden had advised that this code contains triangular joins and we must use this carefully or rather refrain from it!

    If it just a assignment,then this should work for you!

    The real code:

    DECLARE @People

    TABLE (

    person_id INTEGER IDENTITY(0,1) PRIMARY KEY,

    name VARCHAR(10) NOT NULL

    );

    INSERT @People (name) VALUES ('Alan');

    INSERT @People (name) VALUES ('Bob');

    INSERT @People (name) VALUES ('Carol');

    INSERT @People (name) VALUES ('Debra');

    INSERT @People (name) VALUES ('Eric');

    INSERT @People (name) VALUES ('Frank');

    INSERT @People (name) VALUES ('Gina');

    INSERT @People (name) VALUES ('Harry');

    INSERT @People (name) VALUES ('Ian');

    INSERT @People (name) VALUES ('Julie');

    DECLARE @Bits

    TABLE (

    bit_id BIGINT NOT NULL PRIMARY KEY,

    value BIGINT NOT NULL

    );

    INSERT @Bits (bit_id, value)

    SELECT P.person_id - 1, POWER(2, (P.person_id - 1))

    FROM @People P;

    DECLARE @Grouped

    TABLE (

    N BIGINT NOT NULL,

    name VARCHAR(10) NOT NULL,

    group_size BIGINT NOT NULL,

    group_order BIGINT NOT NULL,

    group_row BIGINT NOT NULL,

    UNIQUE (N, name),

    UNIQUE (group_row, group_size, group_order, N)

    );

    INSERT @Grouped

    (N, name, group_size, group_order, group_row)

    SELECT Q.N,

    Q.name,

    Q.group_size,

    group_order = DENSE_RANK() OVER (PARTITION BY Q.group_size ORDER BY Q.N),

    group_row = DENSE_RANK() OVER (PARTITION BY Q.group_size ORDER BY Q.name)

    FROM (

    SELECT N.N,

    P.name,

    group_size = COUNT(*) OVER (PARTITION BY N.N)

    FROM dbo.Numbers (POWER(2, (SELECT COUNT(*) FROM @People))) N

    JOIN @Bits B

    ON N.N & B.value = B.value

    JOIN @People P

    ON P.person_id = B.bit_id

    ) Q

    SELECT names =

    STUFF

    (

    (

    SELECT ',' + name

    FROM @Grouped T2

    WHERE T2.N = T1.N

    ORDER BY

    name ASC

    FOR XML PATH('')

    )

    , 1, 1, SPACE(0))

    FROM @Grouped T1

    WHERE group_row = 1

    ORDER BY

    T1.group_size,

    T1.group_order;

    GO

    The code for Numbers Function in that:

    DROP FUNCTION dbo.Numbers;

    GO

    CREATE FUNCTION dbo.Numbers

    (@N BIGINT)

    RETURNS TABLE

    WITH SCHEMABINDING

    AS RETURN

    WITH

    N1 AS (SELECT N = 1 UNION ALL SELECT 1),

    N2 AS (SELECT N = 1 FROM N1 T, N1),

    N3 AS (SELECT N = 1 FROM N2 T, N2),

    N4 AS (SELECT N = 1 FROM N3 T, N3),

    N5 AS (SELECT N = 1 FROM N4 T, N4),

    N6 AS (SELECT N = 1 FROM N5 T, N5),

    NM AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS N FROM N6)

    SELECT TOP (@N)

    N

    FROM NM

    WHERE N <= @N

    ORDER BY

    N ASC;

    GO

    Hope this helps you! But i am expecting Jeff to comment on this!

    😎

    coldcoffee

    N-Way Handshaking code ???

    i am just hearing this word first time. what it is?

    karthik

  • I can put N-Way handshaking as this:

    Assume there are 4 people sitting in the room and assume they are to first hand-shake with each other, then they will pair up in set of 2's and start hand shaking other individuals, then they pair up in set of 3's and hand-shake and so on.. it is actually finding the different combinations of persons handshaking.

    As for the name,it is just a mere name that was used in that thread, thats al.. its not a predefned phrase or method 😀

    hope this info helps you!

  • Gopi Muluka (5/18/2010)


    Try this

    WITH RecCTE AS

    (

    SELECT Convert(VarChar(30),i) i FROM T

    UNION ALL

    SELECT Convert(Varchar(30),t2.i+','+t3.i) as i FROM T T2

    CROSS JOIN RecCTE T3

    WHERE t2.i<>t3.i AND t2.i<LEFT(t3.i,1)

    )

    SELECT * FROM RecCTE

    ORDER BY LEN(I),i

    Thanks. It seems like run like a magic! (I need to spend enough time to find the logic behind the code)

    Also thanks ColdCoffee for the CODE, I will spend time on it.

  • The solution (at the second post in this topic) will not word when my sample data be like following, and my desire result is:

    Declare @t table (id int, score int)

    insert @t select 1, 1

    union select 20, 3

    union select 300, 4

    union select 4000, 2;

    select * from @t

    /*

    id score

    ----------- -----------

    1 1

    20 3

    300 4

    4000 2

    */

    /*

    elements sum(score)

    ------------ ------------

    1 1

    20 3

    300

    4000

    1,20 4

    1,300

    1,4000

    20,300

    20,4000

    300,4000

    ...

    ...

    1,20,300,400 10

  • Okay I find the mistake and fix it

    Here the solution:

    Declare @t table (id int, score int)

    insert @t select 1, 1

    union select 20, 3

    union select 300, 4

    union select 4000, 2;

    select * from @t

    /*

    id score

    ----------- -----------

    1 1

    20 3

    300 4

    4000 2

    */

    ;WITH RecCTE AS

    (

    SELECT Convert(VarChar(30),id) id, score

    FROM @T

    UNION ALL

    SELECT Convert(Varchar(30),cast(t2.id as varchar(10)) + ',' + cast(t3.id as varchar(10))) as id, t2.score + t3.score as score

    FROM @T T2

    CROSS JOIN RecCTE T3

    WHERE cast(t2.id as varchar(10)) <> t3.id

    AND t2.id < LEFT(t3.id,charindex(',',t3.id+',')-1)

    )

    SELECT * FROM RecCTE

    ORDER BY id,LEN(id)

    /*

    id score

    ------------------------------ -----------

    1 1

    1,20 4

    1,20,300 8

    1,20,300,400 10

    1,20,4000 6

    1,300 5

    1,300,4000 7

    1,4000 3

    20 3

    20,300 7

    20,300,4000 9

    20,4000 5

    300 4

    300,4000 6

    4000 2

    */

Viewing 10 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic. Login to reply