按某列分组以获得总值,并按某列以相反顺序求和

时间:2019-05-29 02:32:49

标签: sql sql-server

表格和DDL:

|id |gooditem|amt  |
|---|--------|-----|
|1  |apple   |1000 |
|2  |apple   |2000 |
|3  |apple   |-3000|
|4  |apple   |500  |
|5  |apple   |1500 |
|6  |pen     |1000 |
|7  |pen     |2000 |
|8  |pen     |-3000|
|9  |pen     |500  |
|10 |pen     |2500 |
CREATE TABLE T
    ([id] int, [gooditem] varchar(5), [amt] int)
;

INSERT INTO T
    ([id], [gooditem], [amt])
VALUES
    (1, 'apple', 1000),
    (2, 'apple', 2000),
    (3, 'apple', -3000),
    (4, 'apple', 500),
    (5, 'apple', 1500),
    (6, 'pen', 1000),
    (7, 'pen', 2000),
    (8, 'pen', -3000),
    (9, 'pen', 500),
    (10, 'pen', 2500)
;

Test Demo Link

逻辑

  • 产品foo的总数量为2000,笔为3000
  • 按ID以相反顺序求和

预期结果

|id |gooditem|amt  |formula                      |total_amt|
|---|--------|-----|-----------------------------|---------|
|1  |foo     |1000 |2000-1500-500--3000-2000-1000|0        |
|2  |foo     |2000 |2000-1500-500--3000-2000     |1000     |
|3  |foo     |-3000|2000-1500-500--3000          |3000     |
|4  |foo     |500  |2000-1500-500                |0        |
|5  |foo     |1500 |2000-1500                    |500      |
|6  |pen     |1000 |3000-1500-500--3000-2000-1000|0        |
|7  |pen     |2000 |3000-1500-500--3000-2000     |1000     |
|8  |pen     |-3000|3000-1500-500--3000          |2000     |
|9  |pen     |500  |3000-1500-500                |1000        |
|10 |pen     |1500 |3000-1500                    |1500      |

我的尝试与问题

我尝试使用rownumber()来订购ID,然后使用ID总和数据。 但我在按好项目to get total value and sum the value in reverse order by somecolumn

分组时遇到问题

版本

  

Microsoft SQL Server 2008 R2(RTM)-10.50.1600.1(X64)


我对sql server 2008的回答

with cte as (
    select row_number() over (partition by [gooditem] order by id desc) rnk
       ,sum(T1.amt) over (partition by T1.gooditem)  total_amt,* 
    from T T1
)
,cte2 as (
    select T1.gooditem ,T1.id,T1.rnk,T1.amt ,T1.total_amt -T1.amt as total_amt  from cte T1
    where T1.rnk = 1
    union all
    select T1.gooditem ,T1.id,T1.rnk,T1.amt ,T2.total_amt - T1.amt as total_amt from cte T1
    inner join cte2 T2 on T1.[gooditem] = T2.[gooditem] and T1.rnk = T2.rnk+1
)
select T1.id,T1.gooditem,T1.amt ,T1.total_amt
from cte2 T1
order by id 

db<>fiddle

1 个答案:

答案 0 :(得分:1)

您正在寻找累计金额:

select id, gooditem, amt,
       (2000 - sum(amt) over (partition by gooditem order by id desc)) as total_amt
from t
order by id;

Here是db <>小提琴。

编辑:

如果需要总计,也可以使用窗口函数进行计算:

select id, gooditem, amt,
       (sum(amt) over (partition by gooditem) -
        sum(amt) over (partition by gooditem order by id desc)
       ) as total_amt
from t
order by id;

db<>fiddle非常相似。