[sql-server] 누적 합계를 얻는 방법

declare  @t table
    (
        id int,
        SomeNumt int
    )

insert into @t
select 1,10
union
select 2,12
union
select 3,3
union
select 4,15
union
select 5,23


select * from @t

위의 선택은 다음을 반환합니다.

id  SomeNumt
1   10
2   12
3   3
4   15
5   23

다음을 어떻게 얻습니까?

id  srome   CumSrome
1   10  10
2   12  22
3   3   25
4   15  40
5   23  63



답변

select t1.id, t1.SomeNumt, SUM(t2.SomeNumt) as sum
from @t t1
inner join @t t2 on t1.id >= t2.id
group by t1.id, t1.SomeNumt
order by t1.id

SQL 피들 예제

산출

| ID | SOMENUMT | SUM |
-----------------------
|  1 |       10 |  10 |
|  2 |       12 |  22 |
|  3 |        3 |  25 |
|  4 |       15 |  40 |
|  5 |       23 |  63 |

편집 : 이것은 대부분의 DB 플랫폼에서 작동하는 일반화 된 솔루션입니다. 특정 플랫폼 (예 : gareth)에 적합한 솔루션이 더 있으면 사용하십시오!


답변

최신 버전의 SQL Server (2012)는 다음을 허용합니다.

SELECT
    RowID,
    Col1,
    SUM(Col1) OVER(ORDER BY RowId ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Col2
FROM tablehh
ORDER BY RowId

또는

SELECT
    GroupID,
    RowID,
    Col1,
    SUM(Col1) OVER(PARTITION BY GroupID ORDER BY RowId ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Col2
FROM tablehh
ORDER BY RowId

이것은 더 빠릅니다. 분할 된 버전은 5 백만 행이 넘는 34 초 만에 완료됩니다.

다른 답변에서 언급 된 SQL 팀 스레드에 대해 언급 한 Peso에게 감사드립니다.


답변

SQL Server 2012 이후로는 쉬울 수 있습니다.

SELECT id, SomeNumt, sum(SomeNumt) OVER (ORDER BY id) as CumSrome FROM @t

때문에 ORDER BY대한 절 SUM기본적으로 수단 RANGE UNBOUNDED PRECEDING AND CURRENT ROW창 프레임은 (에서 “일반 비고” https://msdn.microsoft.com/en-us/library/ms189461.aspx )


답변

재미를위한 CTE 버전 :

;
WITH  abcd
        AS ( SELECT id
                   ,SomeNumt
                   ,SomeNumt AS MySum
             FROM   @t
             WHERE  id = 1
             UNION ALL
             SELECT t.id
                   ,t.SomeNumt
                   ,t.SomeNumt + a.MySum AS MySum
             FROM   @t AS t
                    JOIN abcd AS a ON a.id = t.id - 1
           )
  SELECT  *  FROM    abcd
OPTION  ( MAXRECURSION 1000 ) -- limit recursion here, or 0 for no limit.

보고:

id          SomeNumt    MySum
----------- ----------- -----------
1           10          10
2           12          22
3           3           25
4           15          40
5           23          63


답변

먼저 더미 데이터가 포함 된 테이블을 생성합니다->

Create Table CUMULATIVESUM (id tinyint , SomeValue tinyint)

**Now let put some data in the table**

Insert Into CUMULATIVESUM

Select 1, 10 union
Select 2, 2  union
Select 3, 6  union
Select 4, 10 

여기 나는 같은 테이블에 합류하고있다 (SELF Joining)

Select c1.ID, c1.SomeValue, c2.SomeValue
From CumulativeSum c1,  CumulativeSum c2
Where c1.id >= c2.ID
Order By c1.id Asc

결과 :

ID  SomeValue   SomeValue
1   10          10
2   2           10
2   2            2
3   6           10
3   6            2
3   6            6
4   10          10
4   10           2
4   10           6
4   10          10

여기서 우리는 이제 t2의 Somevalue를 합하면 ans를 얻습니다.

Select c1.ID, c1.SomeValue, Sum(c2.SomeValue) CumulativeSumValue
From CumulativeSum c1,  CumulativeSum c2
Where c1.id >= c2.ID
Group By c1.ID, c1.SomeValue
Order By c1.id Asc

FOR SQL SERVER 2012 이상 (훨씬 더 나은 성능)

Select c1.ID, c1.SomeValue,
SUM (SomeValue) OVER (ORDER BY c1.ID )
From CumulativeSum c1
Order By c1.id Asc

원하는 결과

ID  SomeValue   CumlativeSumValue
1   10          10
2   2           12
3   6           18
4   10          28

Drop Table CumulativeSum

더미 테이블을 지우십시오


답변

답변이 늦었지만 한 가지 가능성이 더 있습니다 …

CROSS APPLY논리 를 통해 누적 합계 생성을보다 최적화 할 수 있습니다 .

실제 쿼리 계획을 분석 할 때 INNER JOIN& 보다 우수합니다 OVER Clause

/* Create table & populate data */
IF OBJECT_ID('tempdb..#TMP') IS NOT NULL
DROP TABLE #TMP

SELECT * INTO #TMP
FROM (
SELECT 1 AS id
UNION
SELECT 2 AS id
UNION
SELECT 3 AS id
UNION
SELECT 4 AS id
UNION
SELECT 5 AS id
) Tab


/* Using CROSS APPLY
Query cost relative to the batch 17%
*/
SELECT   T1.id,
         T2.CumSum
FROM     #TMP T1
         CROSS APPLY (
         SELECT   SUM(T2.id) AS CumSum
         FROM     #TMP T2
         WHERE    T1.id >= T2.id
         ) T2

/* Using INNER JOIN
Query cost relative to the batch 46%
*/
SELECT   T1.id,
         SUM(T2.id) CumSum
FROM     #TMP T1
         INNER JOIN #TMP T2
                 ON T1.id > = T2.id
GROUP BY T1.id

/* Using OVER clause
Query cost relative to the batch 37%
*/
SELECT   T1.id,
         SUM(T1.id) OVER( PARTITION BY id)
FROM     #TMP T1

Output:-
  id       CumSum
-------   ------- 
   1         1
   2         3
   3         6
   4         10
   5         15


답변

Select *, (Select SUM(SOMENUMT)
From @t S
Where S.id <= M.id)
From @t M