从另一个 table 中的特定点开始 SQL 中的 SUM 值
SUM values in SQL starting from a specific point in another table
我有一个 table,其中列出了 index/order、名称和值。例如,它看起来像这样:
TABLE1:
ID | NAME | VALUE
1 | A | 2
2 | B | 5
3 | C | 2
4 | D | 7
5 | E | 0
现在,我有另一个 table,它有一个随机的 NAME 列表。它只会显示 A、B、C、D 或 E。根据 NAME 是什么,我想计算到达 E 所需的所有值的总和。这有意义吗?
例如,如果我的 table 看起来像这样:
TABLE2:
NAME
D
B
A
我想要在 NAME 旁边增加一列来显示总和。所以 D 会有 7,因为下一个事件是 E。B 必须是 5、2 和 7 的总和,因为 B 是 5,C 是 2,D 是 7。A 的总和是 2, 5、3、7等等。
希望这很容易理解。
除了连接两个 table 和获取 NAME 的当前值外,我实际上没有太多东西。但是我不确定如何递增等等并继续添加?
SELECT T2.NAME, T1.VALUE
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.NAME = T2.NAME
这样做有可能吗?还是我在浪费时间?我应该参考实际代码来做到这一点吗?或者我应该做一个功能?
我不知道从哪里开始,我希望有人能帮助我。
提前致谢!
CREATE TABLE #tempTable2(name VARCHAR(1))
INSERT INTO #tempTable2(name)
VALUES('D')
INSERT INTO #tempTable2(name)
VALUES('B')
INSERT INTO #tempTable2(name)
VALUES('A')
CREATE TABLE #tempTable(id INT, name VARCHAR(1), value INT)
INSERT INTO #temptable(id,name,value)
VALUES(1,'A',2)
INSERT INTO #temptable(id,name,value)
VALUES(2,'B',5)
INSERT INTO #temptable(id,name,value)
VALUES(3,'C',2)
INSERT INTO #temptable(id,name,value)
VALUES(4,'D',7)
INSERT INTO #temptable(id,name,value)
VALUES(5,'E',0)
;WITH x AS
(
SELECT id, value, name, RunningTotal = value
FROM dbo.#temptable
WHERE id = (SELECT MAX(id) FROM #temptable)
UNION ALL
SELECT y.id, y.value, y.name, x.RunningTotal + y.value
FROM x
INNER JOIN dbo.#temptable AS y ON
y.id = x.id - 1
)
SELECT x.id, x.value, x.name, x.RunningTotal
FROM x
JOIN #tempTable2 t2 ON
x.name = t2.name
ORDER BY x.id
DROP TABLE #tempTable
DROP TABLE #tempTable2
正如 gregory 所建议的,您可以使用一个简单的窗口函数来执行此操作,该函数(在本例中)将根据 ID
值汇总当前行之后的所有行,包括当前行。显然,您可以通过多种不同的方式对数据进行切片,不过我会留给您去探索:)
declare @t table(ID int,Name nvarchar(50),Val int);
insert into @t values(1,'A',2),(2,'B',5),(3,'C',2),(4,'D',7),(5,'E',0);
select ID -- The desc makes the preceding work the right way. This is
,Name -- essentially shorthand for "sum(Val) over (order by ID rows between current row and unbounded following)"
,Val -- which is functionally the same, but a lot more typing...
,sum(Val) over (order by ID desc rows unbounded preceding) as s
from @t
order by ID;
将输出:
+----+------+-----+----+
| ID | Name | Val | s |
+----+------+-----+----+
| 1 | A | 2 | 16 |
| 2 | B | 5 | 14 |
| 3 | C | 2 | 9 |
| 4 | D | 7 | 7 |
| 5 | E | 0 | 0 |
+----+------+-----+----+
查询分为两部分;一开始很难看出这一点,所以我将逐一介绍。
第一步:获取滚动总和
将 table1 与任何大于自身的字母相连接:
select *
from table1 t1
inner join table1 t2 on t2.name >= t1.name
order by t1.name
这会产生以下结果 table
+ -- + ---- + ----- + -- + ---- + ----- +
| id | name | value | id | name | value |
+ -- + ---- + ----- + -- + ---- + ----- +
| 1 | A | 2 | 1 | A | 2 |
| 1 | A | 2 | 2 | B | 5 |
| 1 | A | 2 | 3 | C | 2 |
| 1 | A | 2 | 4 | D | 7 |
| 1 | A | 2 | 5 | E | 0 |
| 2 | B | 5 | 2 | B | 5 |
| 2 | B | 5 | 3 | C | 2 |
| 2 | B | 5 | 4 | D | 7 |
| 2 | B | 5 | 5 | E | 0 |
| 3 | C | 2 | 3 | C | 2 |
| 3 | C | 2 | 4 | D | 7 |
| 3 | C | 2 | 5 | E | 0 |
| 4 | D | 7 | 4 | D | 7 |
| 4 | D | 7 | 5 | E | 0 |
| 5 | E | 0 | 5 | E | 0 |
+ -- + ---- + ----- + -- + ---- + ----- +
请注意,如果我们按 t1 中的名称分组,我们可以通过对 t2 中的值求和来获得滚动总和。这个查询
select t1.name,
SUM(t2.value) as SumToE
from table1 t1
inner join table1 t2
on t2.name >= t1.name
group by t1.name
给了我们想要的滚动总和
+ ---- + ------ +
| name | sumToE |
+ ---- + ------ +
| A | 16 |
| B | 14 |
| C | 9 |
| D | 7 |
| E | 0 |
+ ---- + ------ +
注意:这相当于使用窗口函数对集合求和,但通过这种连接技术更容易直观地看到您在做什么。
第 2 步:加入滚动总和
现在你有了每个字母的滚动总和,你只需将它加入 table2 以获得你想要的字母
select t1.*
from table2 t2
inner join (
select t1.name,
SUM(t2.value) as SumToE
from table1 t1
inner join table1 t2
on t2.name >= t1.name
group by t1.name
) t1 on t1.name = t2.name
结果:
+ ---- + ------ +
| name | sumToE |
+ ---- + ------ +
| A | 16 |
| B | 14 |
| D | 7 |
+ ---- + ------ +
我有一个 table,其中列出了 index/order、名称和值。例如,它看起来像这样:
TABLE1:
ID | NAME | VALUE
1 | A | 2
2 | B | 5
3 | C | 2
4 | D | 7
5 | E | 0
现在,我有另一个 table,它有一个随机的 NAME 列表。它只会显示 A、B、C、D 或 E。根据 NAME 是什么,我想计算到达 E 所需的所有值的总和。这有意义吗?
例如,如果我的 table 看起来像这样:
TABLE2:
NAME
D
B
A
我想要在 NAME 旁边增加一列来显示总和。所以 D 会有 7,因为下一个事件是 E。B 必须是 5、2 和 7 的总和,因为 B 是 5,C 是 2,D 是 7。A 的总和是 2, 5、3、7等等。
希望这很容易理解。
除了连接两个 table 和获取 NAME 的当前值外,我实际上没有太多东西。但是我不确定如何递增等等并继续添加?
SELECT T2.NAME, T1.VALUE
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.NAME = T2.NAME
这样做有可能吗?还是我在浪费时间?我应该参考实际代码来做到这一点吗?或者我应该做一个功能?
我不知道从哪里开始,我希望有人能帮助我。
提前致谢!
CREATE TABLE #tempTable2(name VARCHAR(1))
INSERT INTO #tempTable2(name)
VALUES('D')
INSERT INTO #tempTable2(name)
VALUES('B')
INSERT INTO #tempTable2(name)
VALUES('A')
CREATE TABLE #tempTable(id INT, name VARCHAR(1), value INT)
INSERT INTO #temptable(id,name,value)
VALUES(1,'A',2)
INSERT INTO #temptable(id,name,value)
VALUES(2,'B',5)
INSERT INTO #temptable(id,name,value)
VALUES(3,'C',2)
INSERT INTO #temptable(id,name,value)
VALUES(4,'D',7)
INSERT INTO #temptable(id,name,value)
VALUES(5,'E',0)
;WITH x AS
(
SELECT id, value, name, RunningTotal = value
FROM dbo.#temptable
WHERE id = (SELECT MAX(id) FROM #temptable)
UNION ALL
SELECT y.id, y.value, y.name, x.RunningTotal + y.value
FROM x
INNER JOIN dbo.#temptable AS y ON
y.id = x.id - 1
)
SELECT x.id, x.value, x.name, x.RunningTotal
FROM x
JOIN #tempTable2 t2 ON
x.name = t2.name
ORDER BY x.id
DROP TABLE #tempTable
DROP TABLE #tempTable2
正如 gregory 所建议的,您可以使用一个简单的窗口函数来执行此操作,该函数(在本例中)将根据 ID
值汇总当前行之后的所有行,包括当前行。显然,您可以通过多种不同的方式对数据进行切片,不过我会留给您去探索:)
declare @t table(ID int,Name nvarchar(50),Val int);
insert into @t values(1,'A',2),(2,'B',5),(3,'C',2),(4,'D',7),(5,'E',0);
select ID -- The desc makes the preceding work the right way. This is
,Name -- essentially shorthand for "sum(Val) over (order by ID rows between current row and unbounded following)"
,Val -- which is functionally the same, but a lot more typing...
,sum(Val) over (order by ID desc rows unbounded preceding) as s
from @t
order by ID;
将输出:
+----+------+-----+----+
| ID | Name | Val | s |
+----+------+-----+----+
| 1 | A | 2 | 16 |
| 2 | B | 5 | 14 |
| 3 | C | 2 | 9 |
| 4 | D | 7 | 7 |
| 5 | E | 0 | 0 |
+----+------+-----+----+
查询分为两部分;一开始很难看出这一点,所以我将逐一介绍。
第一步:获取滚动总和
将 table1 与任何大于自身的字母相连接:
select *
from table1 t1
inner join table1 t2 on t2.name >= t1.name
order by t1.name
这会产生以下结果 table
+ -- + ---- + ----- + -- + ---- + ----- +
| id | name | value | id | name | value |
+ -- + ---- + ----- + -- + ---- + ----- +
| 1 | A | 2 | 1 | A | 2 |
| 1 | A | 2 | 2 | B | 5 |
| 1 | A | 2 | 3 | C | 2 |
| 1 | A | 2 | 4 | D | 7 |
| 1 | A | 2 | 5 | E | 0 |
| 2 | B | 5 | 2 | B | 5 |
| 2 | B | 5 | 3 | C | 2 |
| 2 | B | 5 | 4 | D | 7 |
| 2 | B | 5 | 5 | E | 0 |
| 3 | C | 2 | 3 | C | 2 |
| 3 | C | 2 | 4 | D | 7 |
| 3 | C | 2 | 5 | E | 0 |
| 4 | D | 7 | 4 | D | 7 |
| 4 | D | 7 | 5 | E | 0 |
| 5 | E | 0 | 5 | E | 0 |
+ -- + ---- + ----- + -- + ---- + ----- +
请注意,如果我们按 t1 中的名称分组,我们可以通过对 t2 中的值求和来获得滚动总和。这个查询
select t1.name,
SUM(t2.value) as SumToE
from table1 t1
inner join table1 t2
on t2.name >= t1.name
group by t1.name
给了我们想要的滚动总和
+ ---- + ------ +
| name | sumToE |
+ ---- + ------ +
| A | 16 |
| B | 14 |
| C | 9 |
| D | 7 |
| E | 0 |
+ ---- + ------ +
注意:这相当于使用窗口函数对集合求和,但通过这种连接技术更容易直观地看到您在做什么。
第 2 步:加入滚动总和
现在你有了每个字母的滚动总和,你只需将它加入 table2 以获得你想要的字母
select t1.*
from table2 t2
inner join (
select t1.name,
SUM(t2.value) as SumToE
from table1 t1
inner join table1 t2
on t2.name >= t1.name
group by t1.name
) t1 on t1.name = t2.name
结果:
+ ---- + ------ +
| name | sumToE |
+ ---- + ------ +
| A | 16 |
| B | 14 |
| D | 7 |
+ ---- + ------ +