Cèilidh Nevling
Cèilidh Nevling

Reputation: 107

SQL Server 2008 math fail

After hunting around on various forums for almost an hour, I've come to the conclusion that SQL server is slightly stupid about simple arithmetic.

I am attempting to utilize a function which, until recently seemed to work just fine. Upon changing out some of the values for a different set of information on the form in use, I get the odd behavior ahead.

The problem is that it is giving me the incorrect result as based on an excel spreadsheet formula.

The formula looks like this:

=IF(D8=0,0,(((D8*C12-C16)*(100-C13)/100+C16)/D8)+(C18*D8))

My SQL looks like this:

(((@DaysBilled * @ContractRate - @ActualPlanDed) * (100 - @InsCover) / 100 + @ActualPlanDed) / @DaysBilled) + (@CoPay * @DaysBilled)

Filling the variables with the given data looks like this:

(((11 * 433 - 15) * (100 - 344) / 100 + 15) / 11) + (15 * 11)

Even stranger, if I use the numbers above (adding .00 to the end of each value) manually in the server environment, it gives me -11405.1200000000

With the values I am giving, it should come out 166.36. Unfortunately, I am getting -886.83

Here is the entire function and how it is called:

ALTER FUNCTION Liability
(
@ClientGUID CHAR(32),
@RecordGUID CHAR(32),
@Type CHAR(3)
)
RETURNS DECIMAL(18,2) AS
BEGIN

DECLARE @ReturnValue decimal(18,2);

    DECLARE @DaysBilled int;
    DECLARE @ContractRate decimal(18,2);
    DECLARE @ActualPlanDed decimal(18,2);
    DECLARE @InsCover decimal(18,2);
    DECLARE @CoPay decimal(18,2);

IF (@Type = 'RTC')
BEGIN   
        SELECT @DaysBilled = RTCDaysBilled, 
                @ContractRate = CAST(REPLACE(REPLACE(ContractRateRTC, ' ',''),'$', '') AS DECIMAL(6,2)),
                @ActualPlanDed = RTCActualPlanDed, 
                @InsCover = InsRTCCover, 
                @CoPay = RTCCoPay
        FROM AccountReconciliation1
        WHERE @ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
        AND @RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
IF (@Type = 'PHP')
BEGIN   
        SELECT @DaysBilled = PHPDaysBilled, 
                @ContractRate = CAST(REPLACE(REPLACE(ContractRatePHP, ' ',''),'$', '') AS DECIMAL(6,2)),
                @ActualPlanDed = PHPActualPlanDed, 
                @InsCover = InsPHPCover, 
                @CoPay = PHPCoPay
        FROM AccountReconciliation1
        WHERE @ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
        AND @RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
IF (@Type = 'IOP')
BEGIN   
        SELECT @DaysBilled = IOPDaysBilled, 
                @ContractRate = CAST(REPLACE(REPLACE(ContractRateIOP, ' ',''),'$', '') AS DECIMAL(6,2)),
                @ActualPlanDed = IOPActualPlanDed, 
                @InsCover = InsIOPCover, 
                @CoPay = IOPCoPay
        FROM AccountReconciliation1
        WHERE @ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
        AND @RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
        IF (@DaysBilled <> 0)
    BEGIN
        SET @ReturnValue = (((@DaysBilled * @ContractRate - @ActualPlanDed)
        *
        (100 - @InsCover) / 100 + @ActualPlanDed)
        /
            @DaysBilled
        )
        +
        (@CoPay * @DaysBilled)
    END
        ELSE
    BEGIN
        SET @ReturnValue = 0;
    END
RETURN @ReturnValue;
END

It is called by running a select statement from our front-end, but the result is the same as calling the function from within management studio:

SELECT dbo.Liability('ClientID','RecordID','PHP') AS Liability

I have been reading about how a unary minus tends to break SQL's math handling, but I'm not entirely sure how to counteract it.

One last stupid trick with this function: It must remain a function. I cannot convert it into a stored procedure because it must be used with our front-end, which cannot utilize stored procedures.

Does SQL server even care about the parentheses? Or is it just ignoring them?

Upvotes: 0

Views: 228

Answers (1)

bummi
bummi

Reputation: 27367

The calculation is correct, it differes of course if you are using float values instead of integers.

For (((11 * 433 - 15) * (100 - 344) / 100 + 15) / 11) + (15 * 11) a value around -886.xx depending in which places integers/floats are used is correct, What makes you believe it should be 166.36?

Upvotes: 1

Related Questions