Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / разбить суммы пропорцианально другой сумме по документам / 20 сообщений из 20, страница 1 из 1
06.02.2020, 19:07
    #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
07.02.2020, 08:18
    #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
07.02.2020, 10:21
    #39923781
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, так можно на ноль поделить
...
Рейтинг: 0 / 0
07.02.2020, 10:25
    #39923783
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
nullin
a_voronin, так можно на ноль поделить
У него же NULLIF
...
Рейтинг: 0 / 0
07.02.2020, 10:33
    #39923791
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
nullin
a_voronin, так можно на ноль поделить


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

Код: sql
1.
IIF(КилометровоеВыражение = 0, 0, ДвухКилометровоеВыражение/КилометровоеВыражение)
...
Рейтинг: 0 / 0
07.02.2020, 10:41
    #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
07.02.2020, 10:49
    #39923802
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, не, километровое выражение в cross apply обернул
...
Рейтинг: 0 / 0
07.02.2020, 13:25
    #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
07.02.2020, 13:46
    #39923927
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, а вот и делящий на ноль появился
...
Рейтинг: 0 / 0
07.02.2020, 17:18
    #39923996
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
nullin
a_voronin, а вот и делящий на ноль появился


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


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

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


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


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


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

Код: sql
1.
0.000001 * SUM(CAST((1000000.0 * A * B) / C AS DECIMAL(38,14))
...
Рейтинг: 0 / 0
10.02.2020, 11:20
    #39924581
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, выглядит странно, и мне кажется тут есть проблема: в запросе данной темы round(), значит если 500(мл) на 3 поделить, и округлить, то получится набор 166.67, 166.67, 166.67 -> 166.66 - ошибка в минус идет. Вот, если было бы floor().
...
Рейтинг: 0 / 0
10.02.2020, 13:42
    #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
10.02.2020, 17:34
    #39924781
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, наверно не совсем понятно выразился, в примере не floor, а round, так что так не прокатит, и способ этот на мой взгляд сомнителен.
...
Рейтинг: 0 / 0
10.02.2020, 18:43
    #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
10.02.2020, 21:21
    #39924943
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
разбить суммы пропорцианально другой сумме по документам
a_voronin, там во какая штука есть:
Код: sql
1.
round(55.7657657, 2, 1) = 55.76


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


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