0

各行IDについて、合計から残っている量を見つけたいテーブルがあります。ただし、金額の昇順です。

id   amount
1    3
2    2
3    1
4    5

結果は次のようになります。

id   remainder
1    10
2    8
3    5
4    0

これを達成する方法について何か考えはありますか?オーバー句が道のりだと思いますが、うまくまとめることができません。ありがとうございます。

4

3 に答える 3

2

RDBMSを指定しなかったので、Postgresqlだと思います;-)

select  *, sum(amount) over() - sum(amount) over(order by amount) as remainder
from tbl;

出力:

| ID | AMOUNT | REMAINDER |
---------------------------
|  3 |      1 |        10 |
|  2 |      2 |         8 |
|  1 |      3 |         5 |
|  4 |      5 |         0 |

仕組み:http ://www.sqlfiddle.com/#!1 / c446a / 5

SQL Server 2012でも機能します:http ://www.sqlfiddle.com/#!6 / c446a / 1

SQLServer2008のソリューションを考えています...


ところで、あなたのIDは単なる行番号ですか?そうである場合は、次のようにします。

select 
  row_number() over(order by amount) as rn
  , sum(amount) over() - sum(amount) over(order by amount) as remainder
from tbl
order by rn;

出力:

| RN | REMAINDER |
------------------
|  1 |        10 |
|  2 |         8 |
|  3 |         5 |
|  4 |         0 |

ただし、IDをそのまま使用する必要があり、最小量を上に移動する場合は、次のようにします。

with a as
(
  select  *, sum(amount) over() - sum(amount) over(order by amount) as remainder,
      row_number() over(order by id) as id_sort,
      row_number() over(order by amount) as amount_sort
  from tbl
)
select a.id, sort.remainder
from a
join a sort on sort.amount_sort = a.id_sort
order by a.id_sort;

出力:

| ID | REMAINDER |
------------------
|  1 |        10 |
|  2 |         8 |
|  3 |         5 |
|  4 |         0 |

ここでクエリの進行を参照してください:http ://www.sqlfiddle.com/#!6 / c446a / 11

于 2012-09-04T13:06:58.620 に答える
1

降順でこれを行うためのより簡単な方法を提供したいだけです。

select id, sum(amount) over (order by id desc) as Remainder
from t

これは、Oracle、SQL Server 2012、およびPostgresで機能します。

一般的な解決策には、自己結合が必要です。

select t.id, coalesce(sum(tafter.amount), 0) as Remainder
from t left outer join
     t tafter
     on t.id < tafter.id
group by t.id
于 2012-09-04T13:21:20.370 に答える
-1

SQL Server 2008の回答、SQL Fiddleを提供できませんbegin。キーワードが削除され、構文エラーが発生するようです。私は自分のマシンでこれをテストしました:

create function RunningTotalGuarded()
returns @ReturnTable table(
    Id int, 
    Amount int not null, 
    RunningTotal int not null, 
    RN int identity(1,1) not null primary key clustered
)

as
begin

  insert into @ReturnTable(id, amount, RunningTotal) 
  select id, amount, 0 from tbl order by amount;

  declare @RunningTotal numeric(16,4) = 0;
  declare @rn_check int = 0;

  update @ReturnTable
    set 
        @rn_check = @rn_check + 1
        ,@RunningTotal = 
        case when rn = @rn_check then
            @RunningTotal + Amount
        else
            1 / 0
        end
        ,RunningTotal = @RunningTotal;     
  return;    
end;

目的の出力を達成するには:

with a as
(
    select *, sum(amount) over() - RunningTotal as remainder
        , row_number() over(order by id) as id_order
    from RunningTotalGuarded()
)
select a.id, amount_order.remainder
from a
inner join a amount_order on amount_order.rn = a.id_order;

保護された現在の合計の根拠:http ://www.ienablemuch.com/2012/05/recursive-cte-is-evil-and-cursor-is.html

より少ない悪を選択してください;-)

于 2012-09-04T14:05:53.383 に答える