Мне нужно сгруппировать строки по некоторым столбцам и по промежуточной сумме, пока она не достигнет порогового значения. Ближе всего я получил запрос, основанный на этом ответе , но это решение не так точно, как мне нужно, потому что сумма должна быть сброшена и перезапущена, когда она достигнет порога.
Вот моя попытка с некоторыми примерами данных и порогом 100:
drop table #table
create table #table (
Id int not null,
GroupId int not null,
Code nvarchar(14) not null,
Total int not null
)
insert into #table values
( 1, 1, '1111', 20),( 2, 1, '1111', 75),( 3, 1, '1111', 40),( 4, 1, '1111', 20),
( 5, 1, '1111', 20),( 6, 1, '1111', 25),( 7, 1, '2222', 20),( 8, 1, '2222', 20),
( 9, 1, '2222', 20),(10, 1, '2222', 20),(11, 2, '3333', 10),(12, 2, '3333', 90),
(13, 2, '3333', 90),(14, 2, '3333', 90),(15, 2, '3333', 90),(16, 2, '3333', 10),
(17, 2, '3333', 10),(18, 2, '3333', 10),(19, 2, '3333', 10),(20, 2, '3333', 10),
(21, 2, '3333', 10),(22, 2, '3333', 10),(23, 2, '3333', 10),(24, 2, '3333', 10),
(25, 2, '3333', 10),(26, 2, '3333', 10),(27, 2, '3333', 10),(28, 2, '3333', 10),
(29, 2, '3333', 10),(30, 2, '3333', 10),(31, 2, '3333', 10),(32, 2, '3333', 10),
(33, 2, '3333', 10),(34, 2, '3333', 10),(35, 2, '3333', 10)
;with cte as (
select
Id, GroupId, Code, Total,
cast(sum(Total) OVER (ORDER BY Code, id) as int) / 100 AS Limit
from #table
)
select
*,
dense_rank() over(ORDER BY Code, Limit) as Groups
from cte order by id
Это то, что я получаю, я вручную добавил столбец "GroupsExpected", чтобы показать, что на самом деле нужно, чтобы группы были.
| Id | GroupId | Code | Total | Limit | Groups | GroupsExpected |
|----|---------|------|-------|-------|--------|----------------|
| 1 | 1 | 1111 | 20 | 0 | 1 | 1 |
| 2 | 1 | 1111 | 75 | 0 | 1 | 1 |
| 3 | 1 | 1111 | 40 | 1 | 2 | 2 |
| 4 | 1 | 1111 | 20 | 1 | 2 | 2 |
| 5 | 1 | 1111 | 20 | 1 | 2 | 2 |
| 6 | 1 | 1111 | 25 | 2 | 3 | 3 |
| 7 | 1 | 2222 | 20 | 2 | 4 | 4 |
| 8 | 1 | 2222 | 20 | 2 | 4 | 4 |
| 9 | 1 | 2222 | 20 | 2 | 4 | 4 |
| 10 | 1 | 2222 | 20 | 2 | 4 | 4 |
| 11 | 2 | 3333 | 10 | 2 | 5 | 5 |
| 12 | 2 | 3333 | 90 | 3 | 6 | 6 |
| 13 | 2 | 3333 | 90 | 4 | 7 | 7 |
| 14 | 2 | 3333 | 90 | 5 | 8 | 8 |
| 15 | 2 | 3333 | 90 | 6 | 9 | 9 |
| 16 | 2 | 3333 | 10 | 6 | 9 | 10 |
| 17 | 2 | 3333 | 10 | 6 | 9 | 10 |
| 18 | 2 | 3333 | 10 | 6 | 9 | 10 |
| 19 | 2 | 3333 | 10 | 6 | 9 | 10 |
| 20 | 2 | 3333 | 10 | 7 | 10 | 10 |
| 21 | 2 | 3333 | 10 | 7 | 10 | 10 |
| 22 | 2 | 3333 | 10 | 7 | 10 | 10 |
| 23 | 2 | 3333 | 10 | 7 | 10 | 10 |
| 24 | 2 | 3333 | 10 | 7 | 10 | 10 |
| 25 | 2 | 3333 | 10 | 7 | 10 | 11 |
| 26 | 2 | 3333 | 10 | 7 | 10 | 11 |
| 27 | 2 | 3333 | 10 | 7 | 10 | 11 |
| 28 | 2 | 3333 | 10 | 7 | 10 | 11 |
| 29 | 2 | 3333 | 10 | 7 | 10 | 11 |
| 30 | 2 | 3333 | 10 | 8 | 11 | 11 |
| 31 | 2 | 3333 | 10 | 8 | 11 | 11 |
| 32 | 2 | 3333 | 10 | 8 | 11 | 11 |
| 33 | 2 | 3333 | 10 | 8 | 11 | 11 |
| 34 | 2 | 3333 | 10 | 8 | 11 | 12 |
| 35 | 2 | 3333 | 10 | 8 | 11 | 12 |
Сумма столбца Total
для каждой группы не может набрать 100, а группы '9' и '10' достигают этой суммы (их сумма равна 130 и 100 соответственно).
Я также пытался использовать рекурсивный CTE из этого ответа , но в этом случае я не смог сгруппировать по столбцу Code
.
Я мог бы сделать это программно, но у меня есть ощущение, что это можно сделать проще с помощью одного запроса.
Я использую MSSQL 2016.