Запрос на распределение сумм с остатком по нескольким позициям в группе - PullRequest
0 голосов
/ 22 мая 2018

Мне нужен запрос, который будет пересчитывать суммы по нескольким позициям в группе и учитывать все остатки в последней сумме позиции.

В настоящее время я выполняю это, вручную просматривая упорядоченныеРезультаты - использование переменных для хранения, расчета и распределения значений.Это крайне неэффективно при запросе больших объемов данных.

Вот пример кода, иллюстрирующий то, что я пытаюсь выполнить:

if exists(select * from tempdb.dbo.sysobjects where id = object_id('tempdb.dbo.#xpayments'))
    drop table #xpayments


create table #xpayments (
    payment_id int,
    payment_amount decimal(10,2),
    payment_fee decimal(10,2),
    lineitem_id int,
    lineitem_amount decimal(10,2),
    lineitem_fee decimal(10,2))

insert into #xpayments (payment_id, payment_amount, payment_fee, lineitem_id, lineitem_amount, lineitem_fee) values (1,16.00,1.37,1,10.00,0)
insert into #xpayments (payment_id, payment_amount, payment_fee, lineitem_id, lineitem_amount, lineitem_fee) values (1,16.00,1.37,2,5.00,0)
insert into #xpayments (payment_id, payment_amount, payment_fee, lineitem_id, lineitem_amount, lineitem_fee) values (1,16.00,1.37,3,1.00,0)

Примечание: сумма платежа и payment_fee являются суммамидля всего платежа - все позиции.

select * from #xpayments

приводит к:

payment_id  payment_amount  payment_fee lineitem_id lineitem_amount lineitem_fee
1           16.00           1.37        1           10.00           0.00
1           16.00           1.37        2           5.00            0.00
1           16.00           1.37        3           1.00            0.00

Теперь вычислите и распределите lineitem_fee для каждой позиции следующим образом:

update #xpayments set lineitem_fee = payment_fee * (lineitem_amount/payment_amount)

приводит к:

payment_id  payment_amount  payment_fee lineitem_id lineitem_amount lineitem_fee
1           16.00           1.37        1           10.00           0.86
1           16.00           1.37        2           5.00            0.43
1           16.00           1.37        3           1.00            0.09

Теперь проверьте результаты:

select payment_id, payment_amount, payment_fee, sum(lineitem_amount) lineitem_sum, sum(lineitem_fee) lineitem_fee_sum 
from #xpayments 
group by payment_id, payment_amount, payment_fee

Результаты:

payment_id  payment_amount  payment_fee lineitem_sum    lineitem_fee_sum
1           16.00           1.37        16.00           1.38

Как вы можете видеть, из-за округления,Расчетная сумма комиссии больше, чем фактическая плата.

Существует ли простой способ рассчитать и использовать остаток для итоговой платы за позицию в выражении запроса?Любая помощь с благодарностью.

1 Ответ

0 голосов
/ 23 мая 2018

Вместо одного оператора UPDATE у вас может быть два оператора обновления.Это должно дать вам ожидаемые результаты.

UPDATE X set lineitem_fee = payment_fee * (lineitem_amount/payment_amount)
FROM #xpayments X JOIN (SELECT MAX(lineitem_id) LastLineItemID,payment_id FROM #xpayments GROUP BY payment_id) S
    ON S.payment_id=X.payment_id
WHERE X.lineitem_id < S.LastLineItemID

UPDATE X set lineitem_fee = payment_fee - lineitem_fee_sum
FROM #xpayments X JOIN (SELECT MAX(lineitem_id) LastLineItemID,sum(lineitem_fee) lineitem_fee_sum,payment_id FROM #xpayments GROUP BY payment_id) S
    ON S.payment_id=X.payment_id
WHERE X.lineitem_id = S.LastLineItemID
...