Можно ли написать SQL -запрос, который автоматически согласовывает/«транзакции» и платежи
-
16-10-2019 - |
Вопрос
Я все еще работаю над упомянутым здесь проектом (http://dba.stackexchange.com/questions/2428/how-do-i-properly-design-a-many-t-many-ghrages-payments-accounting-system )
Система должна дать пользователю возможность либо выплатить конкретные суммы на определенные сборы, либо сделать платежи «вы выясняете». Учитывая структуру таблицы, с которой мы пошли (платежи, платежи, платежи_TO_CHARGES), я хочу немного обмануть. По сути, я ищу удивительно шикарный «Приминный» SQL -запрос, который сделает следующее:
Шаг 1) Возьмите все платежи с оставшимся балансом (в основном кредиты)
Шаг 2) Возьмите все расходы с оставшимся балансом (частично оплачиваемая и т. Д.)
Шаг 3) Вставьте части платежей в таблице платежей_TO_CHARGES, пока не будет больше доступных кредитов или больше нет сборов.
... Я думаю, технически это не примирение настолько, как создание транзакционных данных, но вы понимаете.
Шаги 1 и 2, очевидно, очень просты. Это шаг 3, это убийца. Если в SQL нет шикарного способа сделать это, я полагаю, что я пойду со старой ручной кодированной пошаговой петлей и пост-транзакцией и после платежа_TO_CHAGHT ... просто подумал, что я спрошу.
Заранее спасибо!
РЕДАКТИРОВАТЬ 1:Я придумал этот запрос, чтобы определить, какие заряды имеют оставшийся баланс, но он дает мне ошибку, в которой говорится «неизвестный столбец», оставшиеся_балс 'в «где предложение»::
SELECT
charges.*
, (charges.amount - transactions.total_paid) as remaining_balance
FROM charges
, (SELECT
charge_id
, sum(amount) as total_paid
FROM payments_to_charges
GROUP BY charge_id) as transactions
WHERE charges.member_id = 123
AND charges.id = transactions.charge_id
AND remaining_balance > 0
AND charges.active_on < NOW()
Я уверен, что определенные предметы просто не в порядке, но я не могу понять, что вообще не так с этим конкретным запросом. Должен ли я использовать наличие вместо того, где? Я упускаю что -то еще совершенно очевидное?
Решение
Возможно, вы сможете сделать вставку в Payemnts_to_charges в одном операторе SQL, но я не уверен, что это того стоит. Кажется, что это будет проще построить, отлаживать и поддерживать в процедурном коде. Что-то вроде этого:
CREATE TABLE Payments (PaymentId Number(10), Amount Number(6,2));
CREATE TABLE Charges (ChargeID Number(10), Amount Number(6,2));
CREATE TABLE Payments_To_Charges
(PaymentID Number(10), ChargeID Number(10), Amount Number(6,2));
INSERT INTO Payments VALUES (1,4);
INSERT INTO Payments VALUES (2,4);
INSERT INTO Charges VALUES (1,2);
INSERT INTO Charges VALUES (2,5);
INSERT INTO Charges VALUES (3,6);
INSERT INTO Charges VALUES (4,4);
INSERT INTO Charges VALUES (5,10);
Declare
vPaymentAmount Payments.Amount%Type;
vAppliedAmount Payments_To_Charges.Amount%Type;
Begin
For vPayment In (SELECT PaymentID, Amount FROM Payments) Loop
vPaymentAmount := vPayment.Amount;
For vCharge In (
SELECT ChargeID, Amount FROM
(
SELECT ChargeID, Amount -
NVL((SELECT SUM(Amount) FROM Payments_To_Charges pc
WHERE pc.ChargeID = c.ChargeID),0) Amount
FROM Charges c
) WHERE Amount > 0
) Loop
vAppliedAmount := LEAST(vPaymentAmount, vCharge.Amount);
INSERT INTO Payments_To_Charges (PaymentID, ChargeID, Amount)
VALUES (vPayment.PaymentID, vCharge.ChargeID, vAppliedAmount);
vPaymentAmount := vPaymentAmount - vAppliedAmount;
If (vPaymentAmount = 0) Then
Exit;
End If;
End Loop;
End Loop;
End;
/
SELECT * FROM Payments_To_Charges;
Обновлять:
Остальное_балос - это проблема. Вы не можете ссылаться на псевдоним в пункте «Где. Вы можете либо сделать запрос подпроводом и добавить это условие на более высоком уровне, либо изменить оставшиеся_баловые в предложении «Где» (заряды.amount - transactions.total_paid).