Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Cristiano_Rivaldo Member Откуда: Сообщений: 346 |
Всем привет. В ходе разнесения появилась потребность контролировать получившиеся суммы на максимальное значение.DECLARE @N_Sum_For_Split MONEY = 5.2 -- сумма для разнесения ;WITH t ( ID , -- идентификатор (PK) N_Order, -- порядок сортировки (для нарастающего итога) N_SUM, -- сумма F_DOC, -- идентификатор докуменат (FK) N_Sum_Max_By_Doc -- максимальная сумма в рамках одного документа, которая должна быть после разноски ) AS ( SELECT 1,0,3.5,1,4 UNION ALL SELECT 2,1,1.1,1,4 UNION ALL SELECT 3,2,0.8,2,0.4 ) SELECT t.*, CASE WHEN t.N_Need >= 0 THEN CASE WHEN t.N_Sum <= t.N_Need THEN t.N_Sum ELSE t.N_Need END END N_Sum_Res -- сумма после разноски FROM ( SELECT t.*, @N_Sum_For_Split - ISNULL(LAG(t.N_Sum_Step) OVER (ORDER BY t.N_Order,t.ID) ,0) N_Need -- необходимое количество для разнесения FROM ( SELECT t.*, SUM(t.N_SUM) OVER (ORDER BY N_Order,ID) N_Sum_Step -- нарастающий итог FROM t ) t ) t Сумма все строк в пределах одного F_DOC не должна превышать N_Sum_Max_By_Doc. Как сделать это, не прибегая к еще одной разноске ? Остаток после разнесения = 0.6 (4.6 - 4) для F_Doc = 1 потребуется для следующих итераций разнесения. На примере - одна итерация разнесения (сумма = 5.2). В действительности аналог таблицы t будет очень большим и количество документов тоже. Как это сделать , реализовав это с помощью минимального количества разносок / циклов ? |
25 июн 18, 09:13 [21517701] Ответить | Цитировать Сообщить модератору |
Kopelly Member Откуда: Красноярск Сообщений: 289 |
Cristiano_Rivaldo, @N_Sum_For_Split и N_Sum_Max_By_Doc всегда положительные? |
25 июн 18, 09:37 [21517736] Ответить | Цитировать Сообщить модератору |
Cristiano_Rivaldo Member Откуда: Сообщений: 346 |
Kopelly, Да |
25 июн 18, 09:38 [21517740] Ответить | Цитировать Сообщить модератору |
Cristiano_Rivaldo Member Откуда: Сообщений: 346 |
Подразумевается что отрицательные суммы в t уже пересчитаны и разнесены и теперь там только положительные N_Sum |
25 июн 18, 09:40 [21517745] Ответить | Цитировать Сообщить модератору |
Kopelly Member Откуда: Красноярск Сообщений: 289 |
DECLARE @N_Sum_For_Split MONEY = 4.2 -- сумма для разнесения ;WITH t ( ID , -- идентификатор (PK) N_Order, -- порядок сортировки (для нарастающего итога) N_SUM, -- сумма F_DOC, -- идентификатор докуменат (FK) N_Sum_Max_By_Doc -- максимальная сумма в рамках одного документа, которая должна быть после разноски ) AS ( SELECT 1,0,3.5,1,4 UNION ALL SELECT 2,1,1.1,1,4 UNION ALL SELECT 3,2,0.8,2,0.4 ), Ost_Doc as --Ограничиваем суммы по документам согласно N_Sum_Max_By_Doc ( Select *, case When N_Sum_Max_By_Doc - sum(t.N_SUM) over (Partition by F_DOC Order by N_Order, ID) < 0 Then Case When N_Sum_Max_By_Doc - sum(t.N_SUM) over (Partition by F_DOC Order by N_Order, ID) + t.N_Sum > 0 Then N_Sum_Max_By_Doc - sum(t.N_SUM) over (Partition by F_DOC Order by N_Order, ID) + t.N_Sum else 0 End else N_SUM End as N_SUM_Ost From T ), Ost_all as --Определяем разноски на сумму @N_Sum_For_Split ( Select *, case When @N_Sum_For_Split - sum(t.N_SUM_Ost) over (Order by N_Order, ID) < 0 Then Case When @N_Sum_For_Split - sum(t.N_SUM_Ost) over (Order by N_Order, ID) + t.N_SUM_Ost > 0 Then @N_Sum_For_Split - sum(t.N_SUM_Ost) over (Order by N_Order, ID) + t.N_SUM_Ost else 0 End else N_SUM_Ost End as N_SUM_Ost_All From Ost_Doc t ) Select * From Ost_all |
25 июн 18, 10:38 [21517899] Ответить | Цитировать Сообщить модератору |
Cristiano_Rivaldo Member Откуда: Сообщений: 346 |
Kopelly, Спасибо большое ! |
25 июн 18, 10:46 [21517917] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |