2017-02-17 58 views
3

我正在尝试确定如何根据数量列的累计总数将记录组合​​在一起,以便组大小不超过50个。所需组在组列中给出样本数据下面。SQL运行总数分组极限

有没有办法在SQL(特别是SQL Server 2012)中实现这一点?

感谢您的协助。

ID  Qty  Group 
1  10  1 
2  20  1 
3  30  2 <- 60 greater than 50 so new group 
4  40  3 
5  2  3 
6  3  3 
7  10  4 
8  25  4 
9  15  4 
10  5  5 

回答

2

您可以使用CTE来实现目标。

如果项目中的一个超过50数量,一组仍然能够指出

DECLARE @Data TABLE (ID int identity(1,1) primary key, Qty int) 
INSERT @Data VALUES (10), (20), (30), (40), (2), (3), (10), (25), (15), (5) 

;WITH cte AS 
(
    SELECT ID, Qty, 1 AS [Group], Qty AS RunningTotal FROM @Data WHERE ID = 1 
    UNION ALL 
    SELECT data.ID, data.Qty, 
     -- The group limits to 50 Qty 
     CASE WHEN cte.RunningTotal + data.Qty > 50 THEN cte.[Group] + 1 ELSE cte.[Group] END, 
     -- Reset the running total for each new group 
     data.Qty + CASE WHEN cte.RunningTotal + data.Qty > 50 THEN 0 ELSE cte.RunningTotal END 
    FROM @Data data INNER JOIN cte ON data.ID = cte.ID + 1 
) 
SELECT ID, Qty, [Group] FROM cte 
+0

该解决方案可行,但如果示例数据包含更多行,则递归将超出限制。有没有非递归解决方案? – user824911

0

您需要为此创建一个存储过程。

如果您的数据库中包含Group列,那么在插入新记录时通过获取最大Group值及其Qty列总和值得关注它,否则如果您希望Group列在select语句中计算,那么您必须相应地编码存储过程。

+0

这并不回答问题 – TheGameiswar

0

下面的查询给你你最想要的东西。结果还有一个自联接将计算组大小:

select a.ID, G, sum(b.Qty) as Total 
from (
    select max(ID) as ID, G 
    from (
     select a.ID, sum(b.Qty)/50 as G 
     from T as a join T as b 
     where a.ID >= b.ID 
     group by a.ID 
    ) as A 
    group by G 
) as a join T as b 
where a.ID >= b.ID 
group by a.ID 

ID   G   Total 
---------- ---------- ---------- 
2   0   30   
3   1   60   
8   2   140  
10   3   160  

两个重要技巧:

  1. 使用带不平等自联接获得运行总计
  2. 使用整数除法计算组号。

我在我的canonical SQL页面上讨论这个和其他技术。