按 somecolumn 分组以获得总值并按 somecolumn 以相反的顺序对值求和

Posted

技术标签:

【中文标题】按 somecolumn 分组以获得总值并按 somecolumn 以相反的顺序对值求和【英文标题】:group by somecolumn to get total value and sum the value in reverse order by somecolumn 【发布时间】:2019-05-29 02:32:49 【问题描述】:

表格&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,pen为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 总和数据。 但是我在gooditem 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】:

你正在寻找一个累计和:

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

Here 是一个 dbfiddle。

编辑:

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

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 非常相似。

【讨论】:

谢谢,但是不能使用常量2000,这是我之前试过的问题点 @ITWeiHan 。 . .那只需要累积总和。

以上是关于按 somecolumn 分组以获得总值并按 somecolumn 以相反的顺序对值求和的主要内容,如果未能解决你的问题,请参考以下文章

创建单词列表并按索引分组

MySQL 查找子字符串匹配并按匹配全字分组

将时间间隔从文本转换为数字并按客户时间间隔分组

核心数据按年份分组并按日期排序

如何在 SQL 中按多列分组并按日期排序?

SQLAlchemy:如何按两个字段分组并按日期过滤