Get Geometric Mean for all the records

  • Hi,

    All

    Need Help

    input:

    declare @t table

    (

    val numeric(18,6),

    rownumber numeric(18,6)

    )

    insert into @t

    select 1,1 union all

    select 2,2 union all

    select 3,3 union all

    select 4,4

    OutPut:

    1(1)

    2(1*2)

    6(1*2*3)

    24(1*2*3*4)

    Please help me

  • This is how I managed it.

    --Original Table that holds the data

    Create table Ex

    (

    val numeric(18,6),

    rownumber numeric(18,6)

    )

    --Inserting Data

    insert into Ex

    select 1,1 union all

    select 2,2 union all

    select 3,3 union all

    select 4,4

    --Selecting Geometric Mean

    Declare @t Table(val numeric(18,6), rownumber numeric(18,6) )----temp table for looping

    Declare @t1 Table(gm numeric(18,6) )----temp table for storing result

    Declare

    @temp1 numeric(18,6),

    @temp2 int,

    @loop int = 1,

    @res numeric(18,6) = 1

    Insert Into @t

    Select * From Ex

    Select @temp2 = COUNT(*) From Ex

    While(@loop <= @temp2)

    Begin

    Select Top 1 @temp1 = val From @t

    Set @res = @res * @temp1

    Insert Into @t1 Values(@res)

    Delete From @t Where val = @temp1

    Set @loop = @loop + 1

    End

    --Viewing the result

    Select * From @t1

    But, the pros in this forum might have a better solution. 🙂

    Vinu Vijayan

    For better and faster solutions please check..."How to post data/code on a forum to get the best help" - Jeff Moden[/url] 😉

  • Hi,

    Thanks for your reply.

    I want this Logic without using the Looping concept.

    Thanks.

  • Hi, is there any specific reason why you wouldnt want to use loop for this?

    that seems to be the simplest solution, also, I am assuming that the number of rows and the data in table @t are not static and they can change right?

  • phani.gudmines (4/25/2012)


    .....

    1(1)

    2(1*2)

    6(1*2*3)

    24(1*2*3*4)

    what you have as your requested out is the factorial of the number. do you really want the geometric mean of the 4 entries (take the 4th root of the numbers multiplied together) or the factorial as above.

    if you want the factorial as what you have posted i can do it if you actually want the geometric mean that is nice and easy


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

  • AllaboutSQL (4/25/2012)


    Hi, is there any specific reason why you wouldnt want to use loop for this?

    that seems to be the simplest solution, also, I am assuming that the number of rows and the data in table @t are not static and they can change right?

    you can use a recursive function or cte and not "Loop" (not a while loop but you are still looping) but it is starting to sound like homework so ill leave it at that


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

  • or do you want a product function where if you have the values 1,3,5,7 the result would be 1*3*5*7 and you just happened to use 1234 so it looks like a factorial. once again not the geometric mean but extremely do able with out a loop.


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

  • I know I am doing someone else's homework but I havent worked much on CTE or recursive CTEs and it is like a learning exercise for me. When you say recursive CTE, are you guys talking about something like this -

    with cte1 (val, newval) as

    (

    select 1,1 union all select val+1, (val+1)*newval from cte1 where val <=4

    )

    select * from cte1

    with cte2 (val, newval) as

    (

    select 1,1 union all select val+2, (val+2)*newval from cte2 where val <=7

    )

    select * from cte2

  • yep those are recursive cte's. im currently trying to solve the factorial with a numbers table and i think im close. should have it soon

    EDIT: can only do one value at a time but the factorial is as follows

    With tally (n) AS (SELECT top 100 ROW_NUMBER OVER (ORDER BY (SELECT NULL)) FROM sys.columns)

    DECLARE @fac INT = 1

    SELECT @fac = @fac * n FROM tally where n <= 6

    SELECT @fac


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

  • This looks like a running total problem to me (with multiplications as opposed to additions). Most set-like solutions are going to run into some pretty horrendous triangular joins quite quickly. You could look at Jeff Moden's "Quirky Update" method, but since this particular problem must have quite a small number of rows (as the numbers quickly get very silly), a loop/cursor based solution isn't all that bad...

  • HowardW (4/25/2012)


    This looks like a running total problem to me (with multiplications as opposed to additions). Most set-like solutions are going to run into some pretty horrendous triangular joins quite quickly. You could look at Jeff Moden's "Quirky Update" method, but since this particular problem must have quite a small number of rows (as the numbers quickly get very silly), a loop/cursor based solution isn't all that bad...

    if the OP wants to just multiply all the numbers with out the running total he can use SELECT EXP(SUM(LOG(NumCol))) FROM table[/code] to get the final result. so it depends on what the OP wants. and as stated before this is still not the geometric mean for the records. geometric mean would be SELECT EXP(AVG(LOG(NumCol))) FROM table


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

  • This is what you are trying to do -

    DECLARE @fac INT ;

    set @fac = 1;

    With tally (n) AS (SELECT top 100 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM sys.columns)

    SELECT @fac = @fac * n FROM tally where n <= 6

    SELECT @fac

    and this results into a value of 720.

    What is the difference between doing what you have done and doing the following which I have mentioned in my earlier post -

    with cte1 (val, newval) as

    (

    select 1,1 union all select val+1, (val+1)*newval from cte1 where val <=4

    )

    select * from cte1

  • capn.hector (4/25/2012)


    if the OP wants to just multiply all the numbers with out the running total he can use SELECT EXP(SUM(LOG(NumCol))) FROM table to get the final result.

    It's easy enough to expand that to a running total using a triangular join, but performance is not very scalable:

    WITH n AS (

    SELECT 1 n

    UNION ALL

    SELECT 2 n

    UNION ALL

    SELECT 3 n

    UNION ALL

    SELECT 4 n

    UNION ALL

    SELECT 5 n

    UNION ALL

    SELECT 6 n

    UNION ALL

    SELECT 7 n

    )

    SELECT n.n,EXP(SUM(LOG(n1.n))) FROM n

    INNER JOIN n n1 ON n1.n<=n.n

    GROUP BY n.n

  • AllaboutSQL (4/25/2012)


    This is what you are trying to do -

    DECLARE @fac INT ;

    set @fac = 1;

    With tally (n) AS (SELECT top 100 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM sys.columns)

    SELECT @fac = @fac * n FROM tally where n <= 6

    SELECT @fac

    and this results into a value of 720.

    What is the difference between doing what you have done and doing the following which I have mentioned in my earlier post -

    with cte1 (val, newval) as

    (

    select 1,1 union all select val+1, (val+1)*newval from cte1 where val <=4

    )

    select * from cte1

    mine takes a number from tally and multiplies @fac by it setting @fac to the result where as the recursive cte calculates each new number for the next multiplication. different way to get the same result and over large numbers of values recursive CTE's can be a performance drain. for a factorial the largest we can get with a NUMERIC(38,0) is 33 so the difference over the small number of rows is un noticible. if we add to 32,000 the tally table would be faster.

    DECLARE @fac INT ;

    print '---===TallyTable adding===----'

    SET STATISTICS TIME ON

    set @fac = 1;

    SELECT @fac = @fac + n FROM tally where N <= 32000

    SET STATISTICS TIME OFF

    PRINT '----====RECURSIVE CTE adding ===== ------'

    SET STATISTICS TIME ON;

    with cte1 (val) as

    (

    select 1 union all select val + 1 from cte1 where val <= 32000

    )

    select @fac = val from cte1 OPTION(MAXRECURSION 32000)

    SET STATISTICS TIME OFF

    print '---===SELECT ROW_NUMBER "adding"===----'

    SET STATISTICS TIME ON

    SELECT top 32000 @fac = ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) FROM sys.all_columns a, sys.all_columns b

    SET STATISTICS TIME OFF

    the results

    ---===TallyTable adding===----

    SQL Server Execution Times:

    CPU time = 16 ms, elapsed time = 7 ms.

    ----====RECURSIVE CTE adding ===== ------

    SQL Server Execution Times:

    CPU time = 483 ms, elapsed time = 502 ms.

    ---===SELECT ROW_NUMBER "adding"===----

    SQL Server Execution Times:

    CPU time = 0 ms, elapsed time = 8 ms.


    For faster help in answering any problems Please read How to post data/code on a forum to get the best help - Jeff Moden[/url] for the best way to ask your question.

    For performance Issues see how we like them posted here: How to Post Performance Problems - Gail Shaw[/url]

    Need to Split some strings? Jeff Moden's DelimitedSplit8K[/url]
    Jeff Moden's Cross tab and Pivots Part 1[/url]
    Jeff Moden's Cross tab and Pivots Part 2[/url]

Viewing 14 posts - 1 through 13 (of 13 total)

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