2017-02-17 1 views
3

Я пытаюсь определить, как группировать записи вместе на основе суммарного общего количества столбца Qty, чтобы размер группы не превышал 50. Требуемая группа задается в столбце группы с образцами данных ниже.SQL Running Total Grouped By Limit

Есть ли способ выполнить это в 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

Для этого вам необходимо создать хранимую процедуру.

Если у вас есть столбец «Группа» в вашей базе данных, вам нужно позаботиться об этом, вставив новую запись, извлекая максимальное значение группы и сумму столбца Qty в противном случае, если вы хотите, чтобы столбец «Группа» вычислялся в инструкции 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.