2017-02-07 13 views
1

ここでSQL Server 2012優先度とパーセンテージに基づいて配分する額

は私のテーブルです:

Declare @AmtToDistribute float = 500.00 

DECLARE @TestTable TABLE(TempID INT IDENTITY(1, 1) NOT NULL, 
         VicID INT , 
         VicOrderedAmt MONEY, 
         RemainingBalance MONEY, 
         DistPriority INT, 
         DistPercentOf DECIMAL(5, 2), 
         DistributionAmt MONEY 
         ); 

INSERT INTO @TestTable ([VicID], [VicOrderedAmt], [RemainingBalance], [DistPriority], [DistPercentOf], [DistributionAmt]) 
VALUES (2318, 5.00, 5.00, 1, 60.00, 0), 
     (2319, 50.00, 25, 1, 40.00, 0), 
     (2320, 500.00, 500.0, 2, 33.00, 0), 
     (2321, 500.00, 500.0, 2, 33.00, 0), 
     (2322, 500.00, 500.0, 2, 34.00, 0); 

SELECT * FROM @TestTable; 

Sample table structure

私はそれらの値がゼロに達するまで、私は第一優先に各行に金額を分配することを可能にするクエリを見つけようとしているとそれらの値がゼロに達するまで次の優先順位にジャンプします。キャッチは、ドルの金額がDistPercentOf列に基づいて配分されなければならないということです。たとえば、優先度1の2行は、VicIDがVicOrderedAmtが満たされるまで量の60%を取得した後に最初に量を分割し、次に2番目のVicIdが量の40%を取得します。優先度1の金額が満たされたら、優先度2に移動します。

私はいくつかの投稿を見ましたが、優先度は1つしかありません。

ありがとうございます。

+0

私はそれがアプリケーション層の仕事であり、データベースではないと思う。 – cha

+0

第1のレコードについて、あなたはDistributionAmtを300の500の60%に更新したいが、VicOrderedAmtは5であるしたがって、5に更新されますか?同様に、第2記録50および第3記録33%(500-5-50)= 146.85? –

+0

@ RajeshBhat、それは正しいです。私はこれをカーソルとして今でも持っていますが、それは一点でループに入り、DB上で動作します。ちょうどそれを動作させるためにはちょっとした調整が必要です。 – qwerty1906

答えて

0

このような何か試してみてください:@AmtToDistributeはDistributionAmt列と同じデータ型を持っていることを確認して、丸めエラーを回避するには

Declare @AmtToDistribute MONEY = 500.00 

DECLARE @TestTable TABLE (
    TempID     INT IDENTITY(1, 1) NOT NULL, 
    VicID     INT , 
    VicOrderedAmt   MONEY, 
    RemainingBalance   MONEY, 
    DistPriority    INT, 
    DistPercentOf   DECIMAL(5, 2), 
    DistributionAmt   MONEY 
); 

INSERT INTO @TestTable 
    (VicID, VicOrderedAmt, RemainingBalance, DistPriority, DistPercentOf, DistributionAmt) 
    VALUES (2318, 5.00, 5.00, 1, 60.00, 0) 
    , (2319, 50.00, 25, 1, 40.00, 0) 
    , (2320, 500.00, 500.0, 2, 33.00, 0) 
    , (2321, 500.00, 500.0, 2, 33.00, 0) 
    , (2322, 500.00, 500.0, 2, 34.00, 0); 

WHILE 1=1 BEGIN 
    UPDATE y 
    SET y.DistributionAmt=y.DistributionAmt+y.CurrentDistributedAmt, 
     y.RemainingBalance=y.RemainingBalance-y.CurrentDistributedAmt, 
     @[email protected] 
    FROM (
     SELECT *, 
      CASE WHEN @AmtToDistribute<RemainingBalanceForCurrentPriority 
       THEN CASE 
        WHEN RemainingBalance<@AmtToDistribute*x.DistPercentOf/TotalDistPercent 
        THEN x.RemainingBalance 
        ELSE @AmtToDistribute*x.DistPercentOf/TotalDistPercent 
       END 
       ELSE x.RemainingBalance 
      END AS CurrentDistributedAmt 
     FROM (
      SELECT *, SUM(RemainingBalance) OVER() AS RemainingBalanceForCurrentPriority, 
       SUM(DistPercentOf) OVER() AS TotalDistPercent 
      FROM @TestTable WHERE DistPriority=(
       SELECT MIN(DistPriority) FROM @TestTable 
       WHERE RemainingBalance>0 
      ) AND RemainingBalance>0 
     ) x 
    ) y 

    IF @AmtToDistribute=0 BREAK 
    IF NOT EXISTS (SELECT * FROM @TestTable WHERE RemainingBalance>0) BREAK 
END 

select * From @TestTable; 

を。

後に編集(2017年2月12日):

私は上記のコードでのUPDATE文にいくつかの修正を行いました。

また、より良い丸め動作が得られるので、MONEYの代わりにNUMERIC(19,4)を使用することを検討してください。詳細については、Should you choose the MONEY or DECIMAL(x,y) datatypes in SQL Server?を参照してください。

+0

ありがとう、本当に近いです。これを使用してテーブルとAmtToDistributeをシードし、.0001に固定されているため無限ループに入ります。 ** @AmtToDistribute MONEY = 50.00 ** **、(2319,50.00,50,140,​​00)** – qwerty1906

+0

を宣言しました。上記のコードを少し修正しました。 –

関連する問題