Ist es möglich, eine SQL-Abfrage zu schreiben, die Zahlungen und Gebühren automatisch abgleicht/transaktionalisiert?

dba.stackexchange https://dba.stackexchange.com/questions/3415

  •  16-10-2019
  •  | 
  •  

Frage

Ich arbeite immer noch an dem hier erwähnten Projekt (http://dba.stackexchange.com/questions/2428/how-do-i-properly-design-a-many-to-many-charges-zahlungs-accounting-system). ).

Das System soll dem Benutzer die Möglichkeit geben, entweder bestimmte Beträge für bestimmte Gebühren zu zahlen oder generische Zahlungen vorzunehmen, bei denen Sie selbst entscheiden können.Angesichts der Tabellenstruktur, die wir gewählt haben (PAYMENTS, CHARGES, PAYMENTS_TO_CHARGES), möchte ich ein wenig schummeln.Im Grunde suche ich nach einer erstaunlich schicken „Abgleichs“-SQL-Abfrage, die Folgendes bewirkt:

SCHRITT 1) Holen Sie sich alle Zahlungen mit Restguthaben (im Wesentlichen Guthaben)

SCHRITT 2) Holen Sie sich alle Gebühren mit Restguthaben (teilweise bezahlt usw.)

SCHRITT 3) Fügen Sie Teile der Zahlungen in die Tabelle PAYMENTS_TO_CHARGES ein, bis kein Guthaben mehr verfügbar ist oder keine Gebühren mehr anfallen.

…Ich denke, technisch gesehen handelt es sich dabei weniger um einen Abgleich als vielmehr um die Erstellung von Transaktionsdaten, aber Sie verstehen schon, worauf es ankommt.

Die Schritte 1 und 2 sind offensichtlich sehr einfach.Der Killer ist Schritt 3.Wenn es keine schicke Möglichkeit gibt, dies in SQL zu tun, werde ich wohl mit der alten handcodierten Schritt-für-Schritt-Schleife durch jede Transaktion gehen und payment_to_charge posten ... ich dachte nur, ich frage mal.

Dank im Voraus!

EDIT 1:Ich habe mir diese Abfrage ausgedacht, um festzustellen, welche Gebühren noch übrig sind, aber sie gibt mir eine Fehlermeldung mit der Meldung „Unbekannte Spalte ‚remaining_balance‘ in ‚where-Klausel‘“:

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()

Ich bin mir sicher, dass bestimmte Elemente einfach nicht in Ordnung sind, aber ich kann nicht herausfinden, was bei dieser speziellen Abfrage generell falsch ist.Sollte ich HAVING anstelle von WHERE verwenden?Übersehe ich noch etwas völlig Offensichtliches?

War es hilfreich?

Lösung

Möglicherweise können Sie INSERT in Payemnts_To_Charges in einer SQL-Anweisung ausführen, aber ich bin mir nicht sicher, ob es sich lohnt.Es scheint, dass dies im prozeduralen Code einfacher zu erstellen, zu debuggen und zu warten wäre.Etwas wie das:

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;

Aktualisieren:

„Remaining_balance“ ist das Problem.Sie können in der WHERE-Klausel nicht auf den Aliaswert verweisen.Sie können die Abfrage entweder in eine Unterabfrage umwandeln und diese Bedingung auf einer höheren Ebene hinzufügen oder den verbleibenden Restbetrag in der WHERE-Klausel für (charges.amount - Transactions.total_paid) ändern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top