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?
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?