2

1 つの金額を 2 つのフィールドに分割する必要があります。結果のフィールドの合計 = 最初の行を分割する比率はわかっていますが、結果の合計を丸めてから、次の行の比率を計算する必要があります (したがって、丸められた値の合計は正しくなります)。

ここに画像の説明を入力

このアルゴリズムを Oracle 10g PL/SQL でどのように記述できますか? 移行されたデータをテストする必要があります。これが私が思いついたものです(これまでのところ):

with temp as (
  select 1 id, 200 amount, 642 total_a from dual union all
  select 2, 200, 642 from dual union all
  select 3, 200, 642 from dual union all
  select 4, 200, 642 from dual union all
  select 5, 200, 642 from dual
)
select
  temp2.*,
  remaining_a / remaining_amount ratio,
  round(amount * remaining_a / remaining_amount, 0) rounded_a,
  round(amount - amount * remaining_a / remaining_amount, 0) rounded_b
from (
  select
    temp.id,  
    temp.amount,
    sum(amount) over (
      order by id
      range between current row and unbounded following
    ) remaining_amount,
    case when id=1 then total_a /* else ??? */ end remaining_a
  from temp
) temp2

更新: 上の画像が表示されない場合、期待されるrounded_A値は次

1 128
2 129
3 128
4 129
5 128
4

1 に答える 1

3

これが私の提案です。それはあなたが望むものを正確に得ていません。. . 私の計算では、129 は 3 行目まで来ません。

アイデアは、さらに列を追加することです。行ごとに、推定分割を計算します。次に、累積分数を追跡します。累積剰余が整数を超える場合、A の量を 1 増やします。A の量を取得したら、残りを計算できます。

WITH temp AS (
     SELECT 1 id, 200 amount, 642 total_a FROM dual UNION ALL
     SELECT 2, 200, 642 FROM dual UNION ALL
     SELECT 3, 200, 642 FROM dual UNION ALL
     SELECT 4, 200, 642 FROM dual UNION ALL
     SELECT 5, 200, 642 FROM dual
)
select temp3.*,
       sum(estArem) over (order by id) as cumrem,
       trunc(estA) + (case when trunc(sum(estArem) over (order by id)) > trunc(- estArem + sum(estArem) over (order by id))
                          then 1 else 0 end)
from (SELECT temp2.*,
             trunc(Aratio*amount) as estA,
             Aratio*amount - trunc(ARatio*amount) as estArem
      FROM (SELECT temp.id, temp.amount,
                   sum(amount) over (ORDER BY id range BETWEEN CURRENT ROW AND unbounded following
                              ) remaining_amount,
                   sum(amount) over (partition by null) as total_amount,      
                   max(total_a) over (partition by null)as maxA, 
                   (max(total_a) over (partition by null) /
                    sum(amount) over (partition by null)
                   )  as ARatio
            FROM temp
           ) temp2
      ) temp3

これは正確にはパーティショニングの問題ではありません。これは整数近似の問題です。

値を切り捨てるのではなく丸める場合は、ロジックを少し調整する必要があります。

       trunc(estA) + (case when trunc(sum(0.5+estArem) over (order by id)) > trunc(0.5 - estArem + sum(estArem) over (order by id))

このステートメントはもともと、整数のしきい値を超える累積剰余を探すだけでした。これにより、切り捨てではなく丸めが行われます。

于 2012-07-12T16:10:58.520 に答える