0

さまざまなフォーラムを 1 時間近く探し回った結果、SQL サーバーは単純な算術計算に関しては少し馬鹿げているという結論に達しました。

最近まで問題なく機能していた機能を利用しようとしています。使用中のフォームの別の情報セットの値の一部を変更すると、先に奇妙な動作が発生します。

問題は、Excel スプレッドシートの数式に基づいて間違った結果が得られることです。

式は次のようになります。

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

私のSQLは次のようになります。

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

変数に与えられたデータを入力すると、次のようになります。

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

さらに奇妙なことに、サーバー環境で上記の数字 (各値の末尾に .00 を追加) を手動で使用すると、-11405.1200000000 が返されます。

私が与えている値では、166.36 になるはずです。残念ながら、私は -886.83 を得ています

関数全体とその呼び出し方法は次のとおりです。

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

フロントエンドからselectステートメントを実行することで呼び出されますが、結果は管理スタジオ内から関数を呼び出すのと同じです:

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

単項マイナスがどのように SQL の数学処理を壊す傾向があるかについて読んでいますが、それを打ち消す方法が完全にはわかりません。

この関数の最後の愚かなトリック: 関数のままにしておく必要があります。ストアドプロシージャを利用できないフロントエンドで使用する必要があるため、ストアドプロシージャに変換できません。

SQLサーバーは括弧を気にしますか? それとも無視しているだけですか?

4

1 に答える 1

1

計算は正しいです。もちろん、整数の代わりに浮動小数点値を使用している場合は異なります。

(((11 * 433 - 15) * (100 - 344) / 100 + 15) / 11) + (15 * 11) の場合、整数/浮動小数点数が使用される場所に応じて -886.xx 前後の値が正しいです。 166.36 であるべきだと思いますか?

于 2012-11-29T23:37:46.993 に答える