Reputation: 107
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
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