powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / разбить суммы пропорцианально другой сумме по документам
20 сообщений из 20, страница 1 из 1
разбить суммы пропорцианально другой сумме по документам
    #39923623
Гулин Федор
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день всем.
SQL 2012

Надо разбить 2 суммы бонуса (план и факт) пропорцианально другой сумме по документам

задача вроде станадратная
https://www.sql.ru/forum/1004370/polnoe-proporcionirovanie-summy-po-strokam-s-okrugleniem
оракловский вариант - но там захардокдено последняя строка

В идеале чтобы в последней строке добивалась дельта - (но не обязательно )
я могу и следующим update добить дельту.

Поля счетчика (1,2,3,4) нет в таблице (хотя его можно добавить )- Row_number() - думаю по
поможет здесь


че то гуглом не нарыл примеров хороших на T-sql - хотя уверен 100% что есть (можно англоязычных)

Единственный тонкий момент у меня
это разрядность - сумма бонуса у меня скажем 100$ а разбить надо на 10000 доков
(пока забил 2 знака после запятой )
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923744
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гулин Федор,

Что-то вроде такой конструкции.
Давайте тестовые данные, для конкретики.

Код: sql
1.
		  d4.[A] = ISNULL(d4.[B]*d3.[A] / NULLIF(SUM(d4.[B]) over (PARTITION BY d4.C), 0), 0)
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923781
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, так можно на ноль поделить
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923783
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
a_voronin, так можно на ноль поделить
У него же NULLIF
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923791
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
a_voronin, так можно на ноль поделить


Невнимательны вы, Батенька. Небось пишите

Код: sql
1.
IIF(КилометровоеВыражение = 0, 0, ДвухКилометровоеВыражение/КилометровоеВыражение)
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923797
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg, а да, действительно

ТСу поможет что-то типа такого:
Код: sql
1.
2.
3.
4.
iif(id = last_value(id) over(partition by schet_factura order by amount, id rows between current row and unbounded following)
      and sum(distributed_nds) over(partition by schet_factura) > 0
  , nds - sum(distributed_nds) over(partition by schet_factura)
  , 0)


Где выделено, нужно поставить что-то своё.
Только надо знать, стоит ли, ндс распределять если sum(amount) = 0
fiddle
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923802
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, не, километровое выражение в cross apply обернул
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923915
entrypoint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гулин Федор,
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
-- Тестовые данные
-- --  Суммы по документам
WITH a AS (
    SELECT 1 AS [Ид Документа], 100.51 AS [План], 151.61 [Факт] UNION ALL 
    SELECT 1, 110.52456, 161.62123 UNION ALL 
    SELECT 1, 120.53127, 171.63456 UNION ALL 
    SELECT 1, 130.54678, 181.64789 UNION ALL 
    SELECT 2, 200.51567, 251.61987 UNION ALL 
    SELECT 2, 210.52112, 261.62654 UNION ALL 
    SELECT 2, 220.53997, 271.63345 UNION ALL 
    SELECT 2, 230.54456, 281.64345
), 
-- -- Распределяемые суммы
b AS ( 
    SELECT 1 AS [Ид Документа], 217.45784567 AS [Распределяемая сумма] UNION ALL 
    SELECT 2, 315.78473456
), 
-- Решение
c AS (  
SELECT 
       a.[Ид Документа]
     , a.[План]
     , a.[Факт]
	-- Приведением к MONEY уменьшил точность для наглядности
     , CONVERT(MONEY, b.[Распределяемая сумма] * a.[План]/SUM(a.[План]) OVER(PARTITION BY a.[Ид Документа])) AS [Распределенная Сумма План]
     -- Приведением к MONEY уменьшил точность для наглядности
     , CONVERT(MONEY, b.[Распределяемая сумма] * a.[Факт]/SUM(a.[Факт]) OVER(PARTITION BY a.[Ид Документа])) AS [Распределенная Сумма Факт]
     , b.[Распределяемая сумма]
FROM 
     a
     INNER JOIN b ON b.[Ид Документа] = a.[Ид Документа]), 
d AS (	 
SELECT 
       c.[Ид Документа]
     , c.[План]
     , c.[Факт]
     , c.[Распределенная Сумма План]
     , c.[Распределенная Сумма Факт]
     , c.[Распределяемая сумма]
     , SUM(c.[Распределенная Сумма План]) OVER(PARTITION BY c.[Ид Документа] ORDER BY (SELECT 1) 
            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Накопленная распределенная Сумма План]
     , SUM(c.[Распределенная Сумма Факт]) OVER(PARTITION BY c.[Ид Документа] ORDER BY (SELECT 1) 
		  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Накопленная распределенная Сумма Факт]
FROM 
     c
	)  
-- -- Финал
SELECT 
       d.[Ид Документа]
     , d.[План]
     , IIF(MAX(d.[Накопленная распределенная Сумма План]) OVER(PARTITION BY d.[Ид Документа]) = d.[Накопленная распределенная Сумма План],
			 d.[Распределенная Сумма План]
			 - d.[Накопленная распределенная Сумма План]
			 + d.[Распределяемая сумма], 
			 d.[Распределенная Сумма План]) AS [Распределенная Сумма План] 
     , d.[Факт]
     , IIF(MAX(d.[Накопленная распределенная Сумма Факт]) OVER(PARTITION BY d.[Ид Документа]) = d.[Накопленная распределенная Сумма Факт],
			 d.[Распределенная Сумма Факт]
			 - d.[Накопленная распределенная Сумма Факт]
			 + d.[Распределяемая сумма], 
			 d.[Распределенная Сумма Факт]) AS [Распределенная Сумма Факт]
FROM 
     d 

...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923927
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, а вот и делящий на ноль появился
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39923996
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
a_voronin, а вот и делящий на ноль появился


Это вы заключили лишь оттого, что сумма в знаменателе стоит?
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924014
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, это про entrypoint
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924018
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
a_voronin, это про entrypoint


А по вашему нет других способов предотвратить деление на 0. Например, иметь констрейнт, что поле > 0.

CONVERT(MONEY, b.[Распределяемая сумма] * a.[Факт]/SUM(a.[Факт]) OVER(PARTITION BY a.[Ид Документа])) AS [Распределенная Сумма Факт]
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924030
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, нет смысла обсуждать констрейнты, т.к. в данном случае это может быть уже уровень бизнес-логики, например в срезе по ключевым датам [факт] может быть и ноль (особенно на такое понимание подталкивает то, что есть [план]), плюс ещё один фактор далее.
В примере CTE, но, да - это условность, а автор так и не удосужился DDL представить.


Кстати эта тема не только на Oracle всплывала, помню и здесь за последние полгода - год, что-то такое было, там ещё, помнится Kopelly помог и кажется его вариант отличался от всех представленных на текущий момент.
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924039
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
nullin, Вот нашел тему, все-таки немного другое там было задание, но у ТС как раз возникла проблема, в том, что общее - убрать ошибку округления.
В теме на Oracle как-то этот момент захардкодили, умельцы


Насколько важно наименовать темы в соответствии с решаемой проблемой
Помогите с запросом
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924518
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
но у ТС как раз возникла проблема, в том, что общее - убрать ошибку округления.


Я вывел для себя такой хак, для борьбы с ошибками округления.

Код: sql
1.
0.000001 * SUM(CAST((1000000.0 * A * B) / C AS DECIMAL(38,14))
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924581
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, выглядит странно, и мне кажется тут есть проблема: в запросе данной темы round(), значит если 500(мл) на 3 поделить, и округлить, то получится набор 166.67, 166.67, 166.67 -> 166.66 - ошибка в минус идет. Вот, если было бы floor().
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924666
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
a_voronin, выглядит странно, и мне кажется тут есть проблема: в запросе данной темы round(), значит если 500(мл) на 3 поделить, и округлить, то получится набор 166.67, 166.67, 166.67 -> 166.66 - ошибка в минус идет. Вот, если было бы floor().


CAST(X AS DECIMAL(18,2)) вам сделает FLOOR
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924781
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, наверно не совсем понятно выразился, в примере не floor, а round, так что так не прокатит, и способ этот на мой взгляд сомнителен.
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924854
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin,

Вот такой хак прокатит FLOOR(X * 100) * 0.01

Код: sql
1.
2.
SELECT CAST(X AS DECIMAL(10,2)), ROUND(X, 2), FLOOR(X * 100) * 0.01
FROM (VALUES (1.001), (1.4999), (1.4899), (1.4499), (1.4450), (1.44499), (1.5000), (1.50001), (1.9999)) t (X)
...
Рейтинг: 0 / 0
разбить суммы пропорцианально другой сумме по документам
    #39924943
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a_voronin, там во какая штука есть:
Код: sql
1.
round(55.7657657, 2, 1) = 55.76


По умолчанию вместо единицы - ноль. Если поставить что-либо отличное от нуля, то будет усекать.
В итоге поправка для распределения 500 на 3, будет +0.02, а не -0.01
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / разбить суммы пропорцианально другой сумме по документам
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]