How to partition records into groups defined by the total sum of a certain column?

时间:2016-06-18 20:11:32

标签: sql sql-server sql-server-2012

For example, consider the following data:

DECLARE @data TABLE (Id INT, Value INT)
INSERT INTO @data VALUES
(0,1),
(1,2),
(2,3),
(3,1),
(4,1),
(5,1)

I want to transform this data into the following:

Id  Value  Group
0   1      0
1   2      0
2   3      1
3   1      2
4   1      2
5   1      2

When inspecting the items in the order of their Ids we compute the total running sum of Value. When it reaches 3 we say the group is complete and start a new group and a new total running sum. This way the given data produces 3 groups (when inspected in the specific order, of course).

Can I compute the Group in Sql Server 2012?

Please, note that this example is somewhat contrived. The real numbers are larger and there are many of them. The sum threshold may as well be a BIGINT.

2 个答案:

答案 0 :(得分:2)

如果第一个值是min。 1,所有源值都是INT /(TINY,SMALL,INT或BIG)然后我会使用以下查询

SELECT *
FROM (
SELECT *, (SUM(v.Value) OVER(ORDER BY v.Id) - 1) / 3 AS Grp
    FROM @data v
) a

Demo

答案 1 :(得分:1)

;WITH cte AS (
SELECT  Id, 
        [Value],
        [Value] as sum_val, 
        0 as grp
FROM @data
WHERE Id = 0
UNION ALL
SELECT  d.id,
        d.[Value], 
        CASE WHEN LAG(sum_val,0,0) OVER (ORDER BY c.Id) = 3 OR d.[Value] = 3 THEN d.[Value] ELSE sum_val+c.[Value] END, 
        CASE WHEN LAG(sum_val,0,0) OVER (ORDER BY c.Id) = 3 OR d.[Value] = 3 THEN grp+1 ELSE grp END
FROM @data d
INNER JOIN cte c
    ON d.Id = c.Id+1
)

SELECT  id,
        [Value],
        grp
FROM cte

会给你:

id  Value   grp
0   1       0
1   2       0
2   3       1
3   1       2
4   1       2
5   1       2

如果添加

(6,2),
(7,0),
(8,1),
(9,3)

@data表,输出将为:

id  Value   grp
0   1       0
1   2       0
2   3       1
3   1       2
4   1       2
5   1       2
6   2       3
7   0       3
8   1       3
9   3       4

我想如果你通过f.e.将会出现问题。 (0,2),(1,2),如何在这种情况下统计小组?