PHISSUG

Home of Filipino Sql Server Enthusiasts
Welcome to PHISSUG Sign in | Join | Help
in Search

[PROBLEM] TSQL Query Contest Open For All :)

Last post 10-24-2006, 8:41 PM by joven. 98 replies.
Page 4 of 7 (99 items)   « First ... < Previous 2 3 4 5 6 Next > ... Last »
Sort Posts: Previous Next
  •  08-23-2006, 6:15 PM 145 in reply to 139

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    what about forming a small group to work on this?

    by our powers combined...
  •  09-22-2006, 5:45 AM 325 in reply to 26

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    master gg,

    kainis last week ko lang nabasa 'tong thread. i know its late na and most probably you already found the solution already Wink [;)]. anyway, share ko na lang din yun solution ko Big Smile [:D]

    hmm i have encountered this kind of problem na before, back on vb6 days pa hehehe, yung problem naman was to create a program that will give the all the possible combinations of cd tracks that can be transfered to a cassete tape. and the rule is, that each side of the tape will consume its maximum length. so yun, parang same scenario lang sya dito sa problem natin hehehe. bale inapply ko na lang ulit yung algo hehehe.

    to explain naman yung approach ko, if we look at the nature of the problem that master gg gave, we can see easily see that it's a permutation problem, where in we need to find first all the DISTINCT permutations/combinations. then find the sum of each combination. in short BRUTE FORCE hehehe.

    share ko din cguro yung steps that i wrote down before i started coding

    1. find the formula for permutation
    2. find the formula for distinct permutation
    (
    http://mathforum.org/dr.math/faq/faq.comb.perm.html)

    3. create table for my sets

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[RefValues]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[RefValues]
    GO

    CREATE TABLE [dbo].[RefValues]
    (
     [RefValueID] [int] IDENTITY (1, 1) NOT FOR REPLICATION  NOT NULL ,
     [RefValue] [numeric](18, 0) NULL
    ) ON [PRIMARY]
    GO

    4. based on the formula, i need to create a function to compute factorial

    CREATE FUNCTION [dbo].[ComputeFactorial]
    ( @nInput int
     , @nLimit int = 0
     , @nDirection int = 1

    RETURNS float
    AS 
    BEGIN

    DECLARE @nFactorial float
    DECLARE @nMultiplier float

    SET @nMultiplier = 1
    IF @nDirection <> 1
     BEGIN
      SET @nDirection = -1
      SET @nMultiplier = @nInput
     END

    IF @nLimit = 0 OR @nLimit IS NULL OR @nLimit > @nInput
     BEGIN
      SET @nLimit = @nInput
     END

    SET @nFactorial = 1

    WHILE @nLimit >= 1
     BEGIN
      SET @nFactorial = @nFactorial * @nMultiplier
      SET @nMultiplier = @nMultiplier + @nDirection
      SET @nLimit = @nLimit - 1
     END
     
    RETURN @nFactorial 

    END

    5. create function to compute permutation of a given set and no. of subsets, i need it to validate the result of my query.

    CREATE FUNCTION [dbo].[ComputePermutation]
    (
     @nSets float
     , @nSubSets float

    RETURNS float
    AS 
    BEGIN

    IF @nSubSets > @nSets
     BEGIN
      SET @nSubSets = @nSets
     END

    DECLARE @nTotalPermutation float
    DECLARE @nFactorialSets float
    DECLARE @nLoopSets float
    DECLARE @nSubSetsPermutation float
    DECLARE @nFactorialSubSets float
    DECLARE @nLoopSubSets float 

    SET @nTotalPermutation = 0
     
    WHILE @nSubSets >= 1
     BEGIN
      SET @nFactorialSets = @nSets
      SET @nLoopSets = @nFactorialSets - 1

      SET @nFactorialSubSets = 1 
      SET @nLoopSubSets = @nSubSets
      SET @nSubSetsPermutation = 0
      
      SELECT @nFactorialSets = dbo.ComputeFactorial(@nSets,@nSubSets,-1)
      SELECT @nFactorialSubSets = dbo.ComputeFactorial(@nSubSets,@nSubSets,1)
      
      SET @nSubSetsPermutation = @nFactorialSets / @nFactorialSubSets
      SET @nTotalPermutation = @nTotalPermutation + @nSubSetsPermutation
      SET @nSubSets = @nSubSets - 1
     END

    RETURN @nTotalPermutation 

    END

    6. create a function to do the permutation/brute force process. my first goal was to create a cursorless approach baka kayang masundot sa cross join hehehe, pero saka na lang hehe result now refactor later! heheh. and during coding i came to realize na SP na lang muna gagamitin ko at wag muna function hehehe and i also need a split function kaya gumawa din ako.

    CREATE FUNCTION [dbo].[Split]
    ( @cDelimiter varchar(5)
     , @cCSV varchar(250)
     , @cNullEmpty varchar(250) = NULL
    )
     
    RETURNS @Column TABLE
    ( CSV  varchar(250)
    )

    AS 

    BEGIN

    DECLARE @nIndex int
    DECLARE @cValue varchar(250)

    SET @nIndex = CHARINDEX(@cDelimiter,@cCSV,0)

    IF @nIndex = 0 
     BEGIN
      SET @cValue = @cCSV
     
      IF @cValue = '' AND @cNullEmpty IS NULL
       BEGIN
        SET @cValue = NULL
       END
      
      IF @cValue = '' AND @cNullEmpty IS NOT NULL
       BEGIN
        SET @cValue = @cNullEmpty
       END
      
      INSERT INTO
       @Column
      SELECT @cValue
      
      SET @cCSV = ''
     END

    WHILE LEN(@cCSV) > 0
     BEGIN
      SET @cValue = LEFT(@cCSV,@nIndex - 1)

      IF @cValue = '' AND @cNullEmpty IS NULL
       BEGIN
        SET @cValue = NULL
       END
      
      IF @cValue = '' AND @cNullEmpty IS NOT NULL
       BEGIN
        SET @cValue = @cNullEmpty
       END

      INSERT
      INTO @Column
      SELECT @cValue
      
      SET @cCSV = RIGHT(@cCSV,LEN(@cCSV) - @nIndex)
      
      SET @nIndex = CHARINDEX(@cDelimiter,@cCSV,0)

      IF @nIndex = 0 
       BEGIN
        SET @cValue = @cCSV

        IF @cValue = '' AND @cNullEmpty IS NULL
         BEGIN
          SET @cValue = NULL
         END
        
        IF @cValue = '' AND @cNullEmpty IS NOT NULL
         BEGIN
          SET @cValue = @cNullEmpty
         END
        
        INSERT
        INTO @Column
        SELECT @cValue
        
        SET @cCSV = ''
       END
     END

    RETURN

    END

    CREATE PROCEDURE [dbo].[GetPermutation]
    (
     @nSet numeric
     , @nSubSet numeric = null
    )
    AS

    DECLARE @nPermutation numeric
    DECLARE @nCombination numeric
    DECLARE @nComboID numeric
    DECLARE @nComboLevel int
    DECLARE @nPrevComboLevel int
    DECLARE @nComboLevelPermutation numeric

    IF @nSubSet IS NULL
     BEGIN
      SET @nCombination = @nSet
     END
    ELSE
     BEGIN
      SET @nCombination = @nSubSet
     END

    SET @nComboLevel = 2
    SET @nComboID = @nSet + 1

    SELECT @nPermutation = dbo.ComputePermutation(@nSet,@nCombination)

    CREATE TABLE #Result
    (
     TotalPermutation numeric
     , ComboLevel int
     , ComboLevelPermutation numeric
     , ComboLevelID int
     , ComboID numeric
     , RefKey varchar(500)
     , RefValueIDPair varchar(500)
     , RefValuePair varchar(500)
     , RefValueID numeric
     , RefValue numeric
     , RefValueSum numeric
    )

    SELECT @nPermutation AS TotalPermutation
     , 1 AS ComboLevel
     , 1 AS ComboLevelPermutation
     , 1 AS ComboLevelID
     , IDENTITY(int,1,1) AS ComboID
     , CONVERT(varchar,RefValueID) + ':' + CONVERT(varchar,RefValue) AS RefKey
     , CONVERT(varchar,RefValueID)  AS RefValueIDPair
     , CONVERT(varchar,RefValueID) + ':' + CONVERT(varchar,RefValue) AS RefValuePair
     , CONVERT(varchar,RefValueID) AS RefValueID
     , RefValue
     , RefValue AS RefValueSum
    INTO #Initial
    FROM RefValues
    ORDER BY
     RefValue
     , RefValueID

    DELETE
    FROM #Initial
    WHERE ComboID > @nSet

    INSERT
    INTO #Result
    SELECT *
    FROM #Initial
    ORDER BY
     RefValue
     , RefValueID

    WHILE @nComboLevel <= @nCombination
     BEGIN
      SET  @nPrevComboLevel = @nComboLevel - 1
      SELECT  @nComboLevelPermutation = dbo.ComputePermutation(@nSet,@nComboLevel) - dbo.ComputePermutation(@nSet,@nPrevComboLevel)
      
      DECLARE @cCurrentRefKey varchar(500)
      DECLARE @nComboLevelID int
      DECLARE @nSortCurrentComboID int

      DECLARE RefKey_Cursor CURSOR FAST_FORWARD FOR
      SELECT DISTINCT
       RefKey
       , ComboID
      FROM #Result
      WHERE ComboLevel = @nPrevComboLevel
      ORDER BY
       ComboID

      OPEN  RefKey_Cursor
      
      FETCH NEXT
      FROM  RefKey_Cursor
      INTO  @cCurrentRefKey
       , @nSortCurrentComboID

      SELECT *
      INTO #TempResult
      FROM #Initial
      ORDER BY
       ComboID

      SET @nComboLevelID = 1

      WHILE @@FETCH_STATUS = 0
       BEGIN   
        DECLARE @cComboRefKey varchar(500)
        DECLARE @nSortComboID int

        DECLARE Combo_Cursor CURSOR FAST_FORWARD FOR
        SELECT DISTINCT
         RefKey
         , ComboID
        FROM  #TempResult
        WHERE RefKey NOT IN (
          SELECT CSV
          FROM Split(',', @cCurrentRefKey, NULL)
         )
        ORDER BY
         ComboID

        OPEN  Combo_Cursor
      
        FETCH NEXT
        FROM  Combo_Cursor
        INTO  @cComboRefKey
         , @nSortComboID   

        WHILE @@FETCH_STATUS = 0
         BEGIN 
          DECLARE @cMaxCurrentValue numeric
          DECLARE @cMaxComboValue numeric
          DECLARE @nRefValueCurrentSum numeric
          DECLARE @nRefValueComboSum numeric
          DECLARE @nRefValueSum numeric
          
          SELECT @cMaxCurrentValue = MAX(ComboID)
           , @nRefValueCurrentSum = SUM(RefValue)
          FROM #Initial
          WHERE RefKey IN (
            SELECT CSV
            FROM Split(',', @cCurrentRefKey, NULL)
           )

          SELECT @cMaxComboValue = MAX(ComboID)
           , @nRefValueComboSum = SUM(RefValue)
          FROM #Initial
          WHERE RefKey IN (
            SELECT CSV
            FROM Split(',', @cComboRefKey, NULL)
           )

          SET @nRefValueSum = @nRefValueCurrentSum + @nRefValueComboSum

          IF @cMaxCurrentValue < @cMaxComboValue
           BEGIN
            SELECT @nPermutation AS TotalPermutation
             , @nComboLevel AS ComboLevel
             , @nComboLevelPermutation AS ComboLevelPermutation
             , @nComboLevelID AS ComboLevelID
             , @nComboID + 0 AS ComboID 
             , @cCurrentRefKey + ',' + @cComboRefKey AS RefKey
             , RefValueIDPair
             , RefValuePair
             , RefValueID
             , RefValue
             , @nRefValueSum AS RefValueSum
            INTO #ComboLevelResult
            FROM #Initial
            WHERE RefKey IN (
              SELECT CSV
              FROM Split(',', @cCurrentRefKey, NULL)
             ) OR
             RefKey IN (
              SELECT CSV
              FROM Split(',', @cComboRefKey, NULL)
             )
      
            INSERT
            INTO #Result
            SELECT *
            FROM #ComboLevelResult
            ORDER BY
             ComboID
             , RefValue
             , RefValueID
             
            SET  @nComboID = @nComboID + 1
            SET  @nComboLevelID = @nComboLevelID + 1
            DROP
            TABLE  #ComboLevelResult
           END
          
          FETCH NEXT
          FROM  Combo_Cursor
          INTO  @cComboRefKey
           , @nSortComboID
         END
        
        CLOSE  Combo_Cursor
        DEALLOCATE Combo_Cursor
        
        DELETE
        FROM #TempResult
        WHERE RefKey = @cCurrentRefKey
       
        FETCH NEXT
        FROM  RefKey_Cursor
        INTO  @cCurrentRefKey
         , @nSortCurrentComboID
       END

      DROP
      TABLE  #TempResult

      CLOSE  RefKey_Cursor
      DEALLOCATE RefKey_Cursor
         
      SET  @nComboLevel = @nComboLevel + 1
      
     END

    SELECT *
    FROM #Result
    ORDER BY
     ComboID

    DROP
    TABLE  #Result

    DROP
    TABLE  #Initial

    7. create a simple SP para sa problem natin,

    CREATE PROCEDURE [dbo].[GetPermutationWithSum]
    (
     @nSets numeric
     , @nSubSets numeric
     , @nFindSum numeric = NULL
    )
    AS
    CREATE TABLE #Result
    (
     TotalPermutation numeric
     , ComboLevel int
     , ComboLevelPermutation numeric
     , ComboLevelID int
     , ComboID numeric
     , RefKey varchar(500)
     , RefValueIDPair varchar(500)
     , RefValuePair varchar(500)
     , RefValueID numeric
     , RefValue numeric
     , RefValueSum numeric
    )

    INSERT
    INTO #Result
    EXEC GetPermutation @nSets, @nSubSets

    SELECT ComboID
     , RefValueID
     , RefValue
    FROM #Result
    WHERE RefValueSum = (CASE WHEN @nFindSum IS NULL THEN RefValueSum ELSE @nFindSum END)

    DROP
    TABLE #Result

     

    ayan hehehe pa test na lang master gg kung pasado ako! Geeked [8-|] hehehe uwi na ko gutom na ako! hehehhe

     

  •  09-22-2006, 6:58 PM 328 in reply to 325

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    wow nice. i'll check on this one later. :)
  •  09-23-2006, 5:31 AM 331 in reply to 328

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    tnx, master gg


    to test pala :

    INSERT VALUES to RefValue Table

    INSERT
    INTO     RefValues
    SELECT    5 AS RefValue
    UNION
    SELECT    10 AS RefValue
    UNION
    SELECT    15 AS RefValue
    UNION
    SELECT    20 AS RefValue


    to get combinations with sum of 20
    EXEC GetPermutationWithSum 4,4,20

    ComboID              RefValueID           RefValue            
    -------------------- -------------------- --------------------
    4                    4                    20
    6                    1                    5
    6                    3                    15

    to get all combinations for 4 values
    EXEC GetPermutationWithSum 4,4,NULL

    ComboID              RefValueID           RefValue            
    -------------------- -------------------- --------------------
    1                    1                    5

    2                    2                    10

    3                    3                    15

    4                    4                    20

    5                    1                    5
    5                    2                    10

    6                    1                    5
    6                    3                    15

    7                    1                    5
    7                    4                    20

    8                    2                    10
    8                    3                    15

    9                    2                    10
    9                    4                    20

    10                   3                    15
    10                   4                    20

    11                   1                    5
    11                   2                    10
    11                   3                    15

    12                   1                    5
    12                   2                    10
    12                   4                    20

    13                   1                    5
    13                   3                    15
    13                   4                    20

    14                   2                    10
    14                   3                    15
    14                   4                    20

    15                   1                    5
    15                   2                    10
    15                   3                    15
    15                   4                    20

    to get all combinations with other info like total permutation, total permutation per sub set etc.
    EXEC GetPermutation 4,4

    to validate total permutation for 4 values with subsets of 1, 2, 3 & 4
    SELECT dbo.ComputePermutation(4,4)
    -----------------------------------------------------
    15.0

    to validate total permutation for subset of 2 elements
    SELECT dbo.ComputePermutation(4,3) - dbo.ComputePermutation(4,2)
    -----------------------------------------------------
    4.0
    -- ComboID 11 to 14


    trivia :

    if we want to find all the DISTINCT combinations from letters A to Z
    SELECT dbo.ComputePermutation(26,26)
    -----------------------------------------------------
    67108863.0 -- DISTINCT combinations! and that's only for letters A to Z with subsets from 1 to 26 combination heheh. add another
    67108863.0 for letters a to z heheh.

    i wonder how long would my script can process all the distinct combination s hmmm... hehheheheh
  •  09-25-2006, 2:20 AM 339 in reply to 331

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    sir ... my initial testing tells me that things seem alright.

    i tried the following:

    7 numbers == 2 seconds (all correct)
    11 numbers == 31 seconds (all correct)
    16 numbers == >1hr and I stopped coz it all ate my memory and drive space where tembdb is located. this is due to heavy use of temp tables.

    i'll setup my sqlserver to have a bigger drive space for tempdb.

    Yes [Y]

    seems like we have the first person to be listed in our "bragging rights" section. :)

    can anybody do some testing too to verify?

  •  09-25-2006, 4:13 AM 340 in reply to 339

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    hehehe yup, i plead guilty to that master glenn, i waited >2hrs testing 26 nos. (67,108,863 combinations) and not succeed, hehehe, i haven't fully refactored my solution but m still in the process (i really got hooked with the problem, guilty again hehehe)

    16 nos. gives only about 65,535 distinct combinations yet, i have spotted some points to refactor already. like, one is during the processing of the #ComboLevelResult, prole' it might be of help of i won't include the other fields yet during that process, and process the RefKey(the comma delimited combinations) first. second is i'll be creating indexed tables na lang instead of temp tables. what do you think guys?

    hmmm.. any ideas?
  •  09-25-2006, 6:25 AM 341 in reply to 340

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    whenever i see one .. I can't help but sing praises. notice how OC this guy is. how the problem was approached, the documentations, even the indentations, the naming conventions ... AND the explanations. whew. crystal clear Yes [Y]
  •  09-25-2006, 6:27 AM 342 in reply to 340

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    rh4m1ll3:
    hehehe yup, i plead guilty to that master glenn, i waited >2hrs testing 26 nos. (67,108,863 combinations) and not succeed, hehehe, i haven't fully refactored my solution but m still in the process (i really got hooked with the problem, guilty again hehehe)

    16 nos. gives only about 65,535 distinct combinations yet, i have spotted some points to refactor already. like, one is during the processing of the #ComboLevelResult, prole' it might be of help of i won't include the other fields yet during that process, and process the RefKey(the comma delimited combinations) first. second is i'll be creating indexed tables na lang instead of temp tables. what do you think guys?

    hmmm.. any ideas?

    sir .. puede ba gg na lang? heheh. wag na master. malayong malayo pa ko level na yan hehe.

    i have not actually analyzed how you coded the solution but at first glance, you might wanna minimize on string manipulation and the use of CONVERT unless it is necessary. these things drag the procs down.

    yep .. if you can avoid the temp table approach you may do so. i dunno if it's possible but you may want to consider too some resource management in every loop that you do. When i ran the proc, it hogged almost all of the PC's resources an never once returned it back :)

  •  09-25-2006, 7:37 PM 346 in reply to 341

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    ggsubscribe:
    whenever i see one .. I can't help but sing praises. notice how OC this guy is. how the problem was approached, the documentations, even the indentations, the naming conventions ... AND the explanations. whew. crystal clear Yes [Y]


    lol! guilty again Wink [;)] hehehe

    declare @seeimnotOCanymore tinyint
    SET @seeimnotOCanymore = 0
  •  09-26-2006, 1:00 AM 353 in reply to 39

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    gg, if you have time, could you run the same tests using my latest script as well?  results may be comparable as long as we're only using small data sets. thanks! Smile [:)]
  •  09-26-2006, 11:17 PM 354 in reply to 353

    Re: [PROBLEM] TSQL Query Contest Open For All :)

    master gg, here's my updates! nakatipid ako almost more than half its processing time than before. ehehhe

    -- 08 - 00:03
    -- 10 - 00:15
    -- 12 - 01:17
    -- 16 - 26:36



    -- ===================
    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Initial]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[Initial]
    GO

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Result]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[Result]
    GO

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[TempResult]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[TempResult]
    GO

    CREATE TABLE [dbo].[Initial] (
        [TotalPermutation] [numeric](18, 0) NULL ,
        [ComboLevel] [int] NULL ,
        [ComboLevelPermutation] [numeric](18, 0) NULL ,
        [ComboLevelID] [int] NULL ,
        [ComboID] [numeric](18, 0) NULL ,
        [RefKey] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueIDPair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValuePair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueID] [numeric](18, 0) NULL ,
        [RefValue] [numeric](18, 0) NULL ,
        [RefValueSum] [numeric](18, 0) NULL
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[Result] (
        [TotalPermutation] [numeric](18, 0) NULL ,
        [ComboLevel] [int] NULL ,
        [ComboLevelPermutation] [numeric](18, 0) NULL ,
        [ComboLevelID] [int] NULL ,
        [ComboID] [numeric](18, 0) NULL ,
        [RefKey] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueIDPair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValuePair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueID] [numeric](18, 0) NULL ,
        [RefValue] [numeric](18, 0) NULL ,
        [RefValueSum] [numeric](18, 0) NULL
    ) ON [PRIMARY]
    GO

    CREATE TABLE [dbo].[TempResult] (
        [TotalPermutation] [numeric](18, 0) NULL ,
        [ComboLevel] [int] NULL ,
        [ComboLevelPermutation] [numeric](18, 0) NULL ,
        [ComboLevelID] [int] NULL ,
        [ComboID] [numeric](18, 0) NULL ,
        [RefKey] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueIDPair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValuePair] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
        [RefValueID] [numeric](18, 0) NULL ,
        [RefValue] [numeric](18, 0) NULL ,
        [RefValueSum] [numeric](18, 0) NULL
    ) ON [PRIMARY]
    GO

     CREATE  INDEX [IX_Initial] ON [dbo].[Initial]([ComboID], [RefKey], [RefValueID], [RefValue]) ON [PRIMARY]
    GO

     CREATE  INDEX [IX_Result] ON [dbo].[Result]([ComboID], [RefKey], [RefValueID], [RefValue]) ON [PRIMARY]
    GO

     CREATE  INDEX [IX_TempResult] ON [dbo].[TempResult]([ComboID], [RefKey], [RefValueID], [RefValue]) ON [PRIMARY]
    GO

    -- ============================

    CREATE PROCEDURE GetPermutation
    (
        @nSet numeric
        , @nSubSet numeric = null
    )
    AS

    SET NOCOUNT ON

    DECLARE @nPermutation numeric
    DECLARE @nCombination numeric
    DECLARE @nComboID numeric
    DECLARE @nComboLevel int
    DECLARE @nPrevComboLevel int
    DECLARE @nComboLevelPermutation numeric

    IF @nSubSet IS NULL
        BEGIN
            SET @nCombination = @nSet
        END
    ELSE
        BEGIN
            SET @nCombination = @nSubSet
        END

    SET     @nComboLevel = 2
    SET     @nComboID = @nSet + 1
    SELECT    @nPermutation = dbo.ComputePermutation(@nSet,@nCombination)

    DELETE
    FROM     Initial

    DELETE
    FROM     TempResult

    DELETE    
    FROM    Result

    SELECT    @nPermutation AS TotalPermutation
        , 1 AS ComboLevel
        , 1 AS ComboLevelPermutation
        , 1 AS ComboLevelID
        , IDENTITY(int,1,1) AS ComboID
        , CONVERT(varchar,RefValueID) + ':' + CONVERT(varchar,RefValue) AS RefKey
        , CONVERT(varchar,RefValueID)  AS RefValueIDPair
        , CONVERT(varchar,RefValueID) + ':' + CONVERT(varchar,RefValue) AS RefValuePair
        , CONVERT(varchar,RefValueID) AS RefValueID
        , RefValue
        , RefValue AS RefValueSum
    INTO    #Initial
    FROM    RefValues
    ORDER BY
        RefValue
        , RefValueID

    DELETE
    FROM    #Initial
    WHERE    ComboID > @nSet

    INSERT
    INTO    Initial
    SELECT    *
    FROM    #Initial

    DROP
    TABLE     #Initial

    INSERT
    INTO    Result
    SELECT    *
    FROM    Initial
    ORDER BY
        RefValue
        , RefValueID

    WHILE @nComboLevel <= @nCombination
        BEGIN
            SET     @nPrevComboLevel = @nComboLevel - 1
            SELECT     @nComboLevelPermutation = dbo.ComputePermutation(@nSet,@nComboLevel) - dbo.ComputePermutation(@nSet,@nPrevComboLevel)
            
            DECLARE @cCurrentRefKey varchar(500)
            DECLARE @nComboLevelID int
            DECLARE @nSortCurrentComboID int

            DECLARE RefKey_Cursor CURSOR FAST_FORWARD FOR
            SELECT    DISTINCT
                RefKey
                , ComboID
            FROM    Result
            WHERE    ComboLevel = @nPrevComboLevel
            ORDER BY
                ComboID

            OPEN     RefKey_Cursor
            
            FETCH NEXT
            FROM     RefKey_Cursor
            INTO     @cCurrentRefKey
                , @nSortCurrentComboID

            INSERT
            INTO    TempResult
            SELECT    *
            FROM    Initial
            ORDER BY
                ComboID

            SET     @nComboLevelID = 1

            WHILE @@FETCH_STATUS = 0
                BEGIN            
                    DECLARE @cComboRefKey varchar(500)
                    DECLARE @nSortComboID int

                    DECLARE Combo_Cursor CURSOR FAST_FORWARD FOR
                    SELECT    DISTINCT
                        RefKey
                        , ComboID
                    FROM     TempResult
                    WHERE    RefKey NOT IN (
                            SELECT    CSV
                            FROM    Split(@cCurrentRefKey, ',', NULL, NULL)
                        )
                    ORDER BY
                        ComboID

                    OPEN     Combo_Cursor
            
                    FETCH NEXT
                    FROM     Combo_Cursor
                    INTO     @cComboRefKey
                        , @nSortComboID            

                    WHILE @@FETCH_STATUS = 0
                        BEGIN    
                            DECLARE @cMaxCurrentValue numeric
                            DECLARE @cMaxComboValue numeric
                            DECLARE @nRefValueCurrentSum numeric
                            DECLARE @nRefValueComboSum numeric
                            DECLARE @nRefValueSum numeric
                            
                            SELECT    @cMaxCurrentValue = MAX(ComboID)
                                , @nRefValueCurrentSum = SUM(RefValue)
                            FROM    Initial
                            WHERE    RefKey IN (
                                    SELECT    CSV
                                    FROM    Split(@cCurrentRefKey, ',', NULL, NULL)
                                )

                            SELECT    @cMaxComboValue = MAX(ComboID)
                                , @nRefValueComboSum = SUM(RefValue)
                            FROM    Initial
                            WHERE    RefKey IN (
                                    SELECT    CSV
                                    FROM    Split(@cComboRefKey, ',', NULL, NULL)
                                )
                            
                            SET     @nRefValueSum = @nRefValueCurrentSum + @nRefValueComboSum

                            IF @cMaxCurrentValue < @cMaxComboValue
                                BEGIN
                                    INSERT
                                    INTO    Result
                                    SELECT    DISTINCT
                                        @nPermutation AS TotalPermutation
                                        , @nComboLevel AS ComboLevel
                                        , @nComboLevelPermutation AS ComboLevelPermutation
                                        , @nComboLevelID AS ComboLevelID
                                        , @nComboID + 0 AS ComboID    
                                        , @cCurrentRefKey + ',' + @cComboRefKey AS RefKey
                                        , RefValueIDPair
                                        , RefValuePair
                                        , RefValueID
                                        , RefValue
                                        , @nRefValueSum AS RefValueSum
                                    FROM    Initial
                                    WHERE    RefKey IN (
                                            SELECT    CSV
                                            FROM    Split(@cCurrentRefKey, ',', NULL, NULL)
                                        ) OR RefKey IN (
                                            SELECT    CSV
                                            FROM    Split(@cComboRefKey,',', NULL, NULL)
                                        )
                                        
                                    SET     @nComboID = @nComboID + 1
                                    SET     @nComboLevelID = @nComboLevelID + 1
                                END
                            ELSE
                                BEGIN    
                                    WHILE @cMaxCurrentValue < @cMaxComboValue
                                        BEGIN
                                            FETCH NEXT
                                            FROM     Combo_Cursor
                                            INTO     @cComboRefKey
                                                , @nSortComboID

                                            SET     @cMaxCurrentValue = @cMaxCurrentValue + 1
                                        END
                                END
                            
                            FETCH NEXT
                            FROM     Combo_Cursor
                            INTO     @cComboRefKey
                                , @nSortComboID
                        END
                    
                    CLOSE     Combo_Cursor
                    DEALLOCATE Combo_Cursor
                    
                    DELETE
                    FROM    TempResult
                    WHERE    RefKey = @cCurrentRefKey
                
                    FETCH NEXT
                    FROM     RefKey_Cursor
                    INTO     @cCurrentRefKey
                        , @nSortCurrentComboID
                END

            DELETE
            FROM     TempResult

            CLOSE     RefKey_Cursor
            DEALLOCATE RefKey_Cursor
                        
            SET     @nComboLevel = @nComboLevel + 1
            
        END

    SELECT    *
    FROM    Result
    ORDER BY
        ComboID

    DELETE
    FROM     Initial

    SET NOCOUNT OFF

    GO


    -- =======================

    here's my updated Split Function


    CREATE  FUNCTION [dbo].[Split]
    (    @cCSV     varchar(8000)
        , @cDelimiter     varchar(5)
        , @cNullEmpty    varchar(8000) = NULL
        , @nGetIndex int = NULL
    )
     
    RETURNS @Column TABLE
    (    Indx    int
        , CSV     varchar(8000)
    )

    AS 

    BEGIN

    DECLARE @nIndex int
    DECLARE    @cValue varchar(8000)
    DECLARE @nIndexCounter int

    SET @nIndexCounter = 0

    SET @nIndex = CHARINDEX(@cDelimiter,@cCSV,0)

    IF @nIndex = 0   
        BEGIN
            SET @cValue = @cCSV
       
            IF @cValue = '' AND @cNullEmpty IS NULL
                BEGIN
                    SET @cValue = NULL
                END
           
            IF @cValue = '' AND @cNullEmpty IS NOT NULL
                BEGIN
                    SET @cValue = @cNullEmpty
                END
           
            IF @nGetIndex = @nIndexCounter OR @nGetIndex IS NULL
                BEGIN
                    INSERT INTO
                        @Column
                    SELECT    @nIndex
                        , @cValue
                END
                           
            SET @nIndexCounter = @nIndexCounter + 1
           
            SET @cCSV = ''
        END

    WHILE LEN(@cCSV) > 0
        BEGIN
            SET @cValue = LEFT(@cCSV,@nIndex - 1)

            IF @cValue = '' AND @cNullEmpty IS NULL
                BEGIN
                    SET @cValue = NULL
                END
           
            IF @cValue = '' AND @cNullEmpty IS NOT NULL
                BEGIN
                    SET @cValue = @cNullEmpty
                END

            IF @nGetIndex = @nIndexCounter OR @nGetIndex IS NULL
                BEGIN
                    INSERT
                    INTO    @Column
                    SELECT    @nIndexCounter
                        , @cValue
                END

            SET @nIndexCounter = @nIndexCounter + 1
           
            SET @cCSV = RIGHT(@cCSV,LEN(@cCSV) - @nIndex)
           
            SET @nIndex = CHARINDEX(@cDelimiter,@cCSV,0)

            IF @nIndex = 0   
                BEGIN
                    SET @cValue = @cCSV

                    IF @cValue = '' AND @cNullEmpty IS NULL
                        BEGIN
                            SET @cValue = NULL
                        END
                   
                    IF @cValue = '' AND @cNullEmpty IS NOT NULL
                        BEGIN
                            SET @cValue = @cNullEmpty
                        END
                   
                    IF @nGetIndex = @nIndexCounter OR @nGetIndex IS NULL
                        BEGIN
                            INSERT
                            INTO    @Column
                            SELECT    @nIndexCounter
                                , @cValue
                        END
                           
                    SET @nIndexCounter = @nIndexCounter + 1
                   
                    SET @cCSV = ''
                END
        END

    RETURN

    END





  •  09-27-2006, 4:15 AM 363 in reply to 354