Smallest Decimal

  • Hey all,

    I have a percentage stored as a decimal as per this:

    87.41 is 87.41%

    It is stored in a decimal (10,7).

    Now the majority are whole numbers. Some have two decimal places. What i am trying to do is find out what the minimum Dp`s i require in the database (i wouldnt be surprised if it were 2 - so a 5,2 would do me).

    I cant think how to code this.

    Any help greatfully received.

    Dan

  • would something like this work for you. not what parsename is intended for but I think it does the trick.

    declare @dec decimal(10,7)

    set @dec = 87.01

    select len(parsename(cast(@dec as float),1) )

    Bob
    -----------------------------------------------------------------------------
    How to post to get the best help[/url]

  • danielfountain (3/22/2012)


    Hey all,

    I have a percentage stored as a decimal as per this:

    87.41 is 87.41%

    It is stored in a decimal (10,7).

    Now the majority are whole numbers. Some have two decimal places. What i am trying to do is find out what the minimum Dp`s i require in the database (i wouldnt be surprised if it were 2 - so a 5,2 would do me).

    I cant think how to code this.

    Any help greatfully received.

    Dan

    May I ask why you want to modify the decimal format? Is it possible that this was selected as it may be possible that they may need more the 2 places to the right of the decimal point? Just trying to play the devils advocate here.

  • how about something like this to figure out the most decimal places used in the table:

    SELECT MAX( CHARINDEX('.',REVERSE(CAST(CAST(val AS float) AS varchar(11)))) -1 )

    FROM tablename

    WHERE CHARINDEX('.',REVERSE(CAST(CAST(val AS float) AS varchar(11)))) > 0

  • How about this?

    DECLARE @tab TABLE ( Num DECIMAL(10,7)) ;

    INSERT @tab (Num)

    SELECT 87.41

    UNION ALL SELECT 1.2

    UNION ALL SELECT 1.0

    UNION ALL SELECT 11

    UNION ALL SELECT 1.22200

    UNION ALL SELECT 1.2980

    UNION ALL SELECT 1.2000000

    UNION ALL SELECT 1.10009

    UNION ALL SELECT 1.6709090

    ;

    ;WITH CTE AS

    (

    SELECT T.Num

    ,DecNum = CASE

    WHEN CEILING(T.Num) = FLOOR(T.Num) THEN 0

    WHEN CEILING(CrsApp1.Dec1) = FLOOR(CrsApp1.Dec1) THEN 1

    WHEN CEILING(CrsApp2.Dec2) = FLOOR(CrsApp2.Dec2) THEN 2

    WHEN CEILING(CrsApp3.Dec3) = FLOOR(CrsApp3.Dec3) THEN 3

    WHEN CEILING(CrsApp4.Dec4) = FLOOR(CrsApp4.Dec4) THEN 4

    WHEN CEILING(CrsApp5.Dec5) = FLOOR(CrsApp5.Dec5) THEN 5

    WHEN CEILING(CrsApp6.Dec6) = FLOOR(CrsApp6.Dec6) THEN 6

    WHEN CEILING(CrsApp7.Dec7) = FLOOR(CrsApp7.Dec7) THEN 7

    END

    FROM @tab T

    CROSS APPLY ( SELECT T.Num * 10 ) CrsApp1 (Dec1)

    CROSS APPLY ( SELECT T.Num * 100 ) CrsApp2 (Dec2)

    CROSS APPLY ( SELECT T.Num * 1000 ) CrsApp3 (Dec3)

    CROSS APPLY ( SELECT T.Num * 10000 ) CrsApp4 (Dec4)

    CROSS APPLY ( SELECT T.Num * 100000 ) CrsApp5 (Dec5)

    CROSS APPLY ( SELECT T.Num * 1000000 ) CrsApp6 (Dec6)

    CROSS APPLY ( SELECT T.Num * 10000000 ) CrsApp7 (Dec7)

    )

    SELECT MaxDigitsAfterDecimal = MAX(C.DecNum)

    FROM CTE C ;

  • Robert klimes (3/22/2012)


    would something like this work for you. not what parsename is intended for but I think it does the trick.

    declare @dec decimal(10,7)

    set @dec = 87.01

    select len(parsename(cast(@dec as float),1) )

    This might produce wrong results because PARSENAME rounds certain values; try this sample data (rows with comments are rounded)

    DECLARE @tab TABLE ( Num DECIMAL(10,7)) ;

    INSERT @tab (Num)

    SELECT 87.41

    UNION ALL SELECT 1.2

    UNION ALL SELECT 1.0

    UNION ALL SELECT 11

    UNION ALL SELECT 1.22200

    UNION ALL SELECT 1.2980

    UNION ALL SELECT 1.2000000

    UNION ALL SELECT 1.10009

    UNION ALL SELECT 1.6709090 -- PARSENAME Rounds this

    UNION ALL SELECT 1.6709999 -- PARSENAME Rounds this

    UNION ALL SELECT 123.009

    ;

    and i dont knwo why it does that! 😀

  • Ouch :pinch: Implicit conversions are causing the rounding

    Look at this:

    declare @dec decimal(10,7)

    set @dec = 1.6709999

    select flt = CAST ( @dec as float)

    , Nvar = CAST ( @dec as nvarchar(23))

    , synam = CAST ( @dec as sysname)

    , fltnvar = CAST ( CAST ( @dec as float) as nvarchar(23))

    , fltsynm = CAST ( CAST ( @dec as float) as sysname)

    <DefinedValue>

    <ColumnReference Column="Expr1005" />

    <ScalarOperator ScalarString="parsename(CONVERT_IMPLICIT(nvarchar(23),CONVERT(float(53),[Num],0),0),(1))">

    <Intrinsic FunctionName="parsename">

    <ScalarOperator>

    <Convert DataType="nvarchar" Length="46" Style="0" Implicit="true">

    <ScalarOperator>

    <Convert DataType="float" Scale="0" Style="0" Implicit="false">

    <ScalarOperator>

    <Identifier>

    <ColumnReference Column="Num" />

    </Identifier>

    </ScalarOperator>

    </Convert>

    </ScalarOperator>

    </Convert>

    </ScalarOperator>

    <ScalarOperator>

    <Const ConstValue="(1)" />

    </ScalarOperator>

    </Intrinsic>

    </ScalarOperator>

    </DefinedValue>

  • Chris Harshman (3/22/2012)


    how about something like this to figure out the most decimal places used in the table:

    SELECT MAX( CHARINDEX('.',REVERSE(CAST(CAST(val AS float) AS varchar(11)))) -1 )

    FROM tablename

    WHERE CHARINDEX('.',REVERSE(CAST(CAST(val AS float) AS varchar(11)))) > 0

    Nope! Again, incorrect results due to data type conversion and rounding!

  • ColdCoffee (3/22/2012)


    Ouch :pinch: Implicit conversions are causing the rounding

    Curse those implicit conversions. Serves me right for not testing it more. :blush:

    Bob
    -----------------------------------------------------------------------------
    How to post to get the best help[/url]

  • actually I think it's the explicit conversion to FLOAT that messes up both of our solutions not any implicit conversion, so ColdCoffee's solution may be brute force, but without an easy way to determine the number of decimal places in a given value it may be the best solution for this problem.

  • Chris Harshman (3/22/2012)


    actually I think it's the explicit conversion to FLOAT that messes up both of our solutions not any implicit conversion

    Acually explicit conversion to FLOAT preserves all the decimal values, but the cast to nvarchat after casting to float or using PARSENAME right over casting of float induces the rounding off. I/Us need to analyze further why this happens.

  • ColdCoffee (3/22/2012)...but the cast to nvarchat after casting to float or using PARSENAME right over casting of float induces the rounding off...

    seems to be a common problem, converting anything from float defaults to only 6 precision. if you use CONVERT function with style 128 it seems to work, but MSDN says 128 setting is depreciated :crazy:

    SELECT MAX( CHARINDEX('.',REVERSE(CONVERT(varchar(20),CAST(val AS float),128))) -1 )

    FROM tablename

    WHERE CHARINDEX('.',REVERSE(CONVERT(varchar(20),CAST(val AS float),128))) > 0

    I suppose it would be easier if you could control the trailing 0's on DECIMAL datatype conversion to VARCHAR instead of having to use FLOAT, but doesn't seem to be a way.

  • Chris Harshman (3/22/2012)


    if you use CONVERT function with style 128 it seems to work, but MSDN says 128 setting is depreciated :crazy:

    :crazy:

    Chris Harshman (3/22/2012)


    I suppose it would be easier if you could control the trailing 0's on DECIMAL datatype conversion to VARCHAR instead of having to use FLOAT, but doesn't seem to be a way.

    xactly. If we had the ability to control the trailing zeros , CAST and LEN would have easily gulped this problem. No funky logic required.

  • Still haven't heard from the OP why he needs this.

  • Lynn Pettis (3/22/2012)


    Still haven't heard from the OP why he needs this.

    Hi,

    The reason i need this is not that i am actually going to change the format - but i want to display the results in reporting services with the least amount of decimal places but without data loss. Having the majority look like 60.0000000 looks silly. However some have 60.5 or 60.55 - what i dont know is to what DP it is used. I dont want to round and lose any data.

    Hope this helps.

    Dan

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

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