我有一張表,我想爲每個行ID找到剩餘總量。但是,金額的順序是按升序排列的。如何計算每行的剩餘金額?
id amount
1 3
2 2
3 1
4 5
結果應該是這樣的:
id remainder
1 10
2 8
3 5
4 0
如何做到這一點有什麼想法?我猜測,過分的條款是要走的路,但我不能把它拼在一起。謝謝。
我有一張表,我想爲每個行ID找到剩餘總量。但是,金額的順序是按升序排列的。如何計算每行的剩餘金額?
id amount
1 3
2 2
3 1
4 5
結果應該是這樣的:
id remainder
1 10
2 8
3 5
4 0
如何做到這一點有什麼想法?我猜測,過分的條款是要走的路,但我不能把它拼在一起。謝謝。
SQL Server 2008中的回答,我不能提供一個SQL小提琴,現在看來,這條的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
選擇兩害取其輕;-)
我會考慮它。謝謝你給我看這個。我很想知道,如果我想使用光標並通過表中的另一個ID拆分總數,我該如何實現這一目標? – user1281598
既然你沒有指定你的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
思考s解決方案SQL Server 2008 ...
順便說一句,你的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
我實際上忽略了另一個規範:我正在通過外部密鑰對這些數量進行排序。將會有另一個整數ID來分割它們。很重要的是忘記我知道的,但能夠在CTE中使用它解決了我的問題的另一部分。謝謝。 – user1281598
我只是想提供一個更簡單的方式按降序爲了做到這一點:
select id, sum(amount) over (order by id desc) as Remainder
from t
這將在甲骨文,SQL Server 2012中,和Postgres工作。
的通解requres自連接:
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
在100行上運行總數相當於硬盤盤片的5,050轉。對於1,000行,它更加指數級,相當於硬盤盤片的500,500轉;-) http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/running-sums-redux.aspx –
@ MichaelBuen。 。 。是的我同意。所有的數據庫供應商都應該支持所有的窗口功能。 –
說如果我想用桌子上的另一個ID進行排序,是使用where子句將它分配給我還是必須使用該id值進行分區? – user1281598
請添加一個標識符,用於標識您使用的特定rdbms –