2017-08-11 2 views
1

Ich arbeite derzeit an einem kleinen Client-Management-System und ich kam über eine Funktion, die ich noch nicht in pure SQL arbeiten kann (derzeit mit PHP foreach mit viel von faulen Laden, so sehr langsam).MySQL - Berechnung der Rechnungssaldo gruppiert nach Client mit 3 Tabellen

Ich versuche, das aktuelle Guthaben von jedem Kunden zu bekommen, so dass die verkaufte jede Rechnung (durch Subtrahieren der Summe der Zahlungen) Zahlung und SUM sie. Jeder Kunde hat Rechnungen in den Systemen und jede Rechnung kann mehrere Zahlungen haben.

Hier ist meine vereinfachte Tabellen zum Zweck generic des Seins:

[Clients] 
- id 
- name 

[Invoices] 
- id 
- client_id 
- amount 

[Payments] 
- id 
- invoice_id 
- amount (positive number) 

Also im Grunde möchte ich dies erhalten:

+--------------------+----------------------+ 
| name    | balance    | 
+--------------------+----------------------+ 
| Client 1   | 342,46    | 
| Client 2   | 0,00     | 
+--------------------+----------------------+ 

die Rechnung verkauft zu bekommen, ich brauche SUM(invoices.amount) - SUM(payments.amount)) aber meine Frage funktioniert überhaupt nicht. Hier ist, was ich bis jetzt bekommen habe:

SELECT DISTINCT 
    c.name, 
    SUM(x.sold) AS balance 
FROM 
    clients AS c 
RIGHT JOIN 
    (
     SELECT SUM(i.invoiceAmount - total_payments) AS sold 
     FROM invoices 
     WHERE i.client_id = c.id 
     RIGHT JOIN (
      SELECT p.id, p.invoice_id, SUM(p.transactionAmount) AS total_payments 
      FROM payments AS p 
      GROUP BY p.invoice_id 
     ) AS p ON p.invoice_id=i.id 
     GROUP BY i.client_id 
    ) AS x ON x.client_id=c.id 
GROUP BY c.name 
ORDER BY c.name ASC 

Hat jemand das schon einmal gemacht? Ich habe es nie getan und es ist ziemlich schwierig.

Hinweis: Ich habe versucht, so allgemein wie möglich zu sein, damit es anderen Menschen in einer ähnlichen Situation helfen kann.

UPDATE: Mit @GordonLinoff Antwort, ich war in der Lage zu bekommen, was ich mit der Abfrage wollte er mir zur Verfügung gestellt.

select name, SUM(invoices - IFNULL(payments, 0)) as balance 
from (
    select name, sum(amount) as invoices, sum(payments) as payments 
    from (select c.id, c.name, i.id as invoiceid, i.amount, sum(p.amount) as payments 
      from clients c left join 
       invoices i 
       on c.id = i.client_id left join 
       payments p 
       on p.invoice_id = i.id 
      group by c.id, c.name, invoiceid, i.amount 
     ) ci 
    group by name 
) x 

Das Ergebnis ist genau so, wie ich es erwartet hatte.

Antwort

1

Aggregation durch hierarchische Strukturen ist schwierig. Hier ist eine Methode, die die Tabellen miteinander verbindet und verwendet dann zwei Aggregationsebenen:

select name, sum(amount) as invoices, sum(payments) as payments 
from (select c.id, c.name, i.id, i.amount, sum(p.amount) as payments 
     from clients c left join 
      invoices i 
      on c.id = i.client_id left join 
      payments p 
      on p.invoice_id = i.id 
     group by c.id, c.name, i.id, i.amount 
    ) ci 
group by name; 
+1

Ich musste einige Anpassungen tun, um meine Tabellen und eine Top-Auswahl passen auch zu 'SUM (Rechnungen - Zahlungen)' und es funktionierte ! Siehe meine Bearbeitung. Die doppelte ID ('c.id' und' i.id') ist jedoch widersprüchlich, ich habe "i.id AS request" umbenannt und es repariert. –

Verwandte Themen