Laufende Zahlen
Laufende Zahlen sind, vereinfacht ausgedrückt, Zahlen, die aufeinander aufaddiert werden. Sie möchten z. B. die Werte von Jahr zu Jahr (YTD) wissen. Die Summierung von Zahlen ist vielleicht ein häufig verwendeter Fall, aber die Möglichkeiten sind nicht darauf beschränkt. Sie könnten auch einen gleitenden Durchschnitt bilden.
In diesem Fall arbeiten wir mit einem YTD-Beispiel. Nehmen wir an, wir haben eine Tabelle mit den Einnahmen für eine bestimmte Kategorie pro Monat.
ea_month id amount ea_year circle_id April 92570 1000 2014 1 April 92571 3000 2014 2 April 92572 2000 2014 3 March 92573 3000 2014 1 March 92574 2500 2014 2 March 92575 3750 2014 3 February 92576 2000 2014 1 February 92577 2500 2014 2 February 92578 1450 2014 3
Um die Gesamtsumme des bisherigen Monats zu erhalten, könnte man versucht sein, eine Unterabfrage wie get all the amount of the previous months of the current year of my product zu verwenden. Das funktioniert tatsächlich, aber für jede abgerufene Zeile wird eine Unterabfrage ausgeführt. Das kann leicht zu tausenden von Abfragen führen und daher wie in diesem Beispiel ewig dauern:
select branch_id, net_profit as store_profit, (select sum(net_profit) from store_sales as s2 where s2.city = s1.city) as city_profit, store_profit / city_profit * 100 as store_percentage_of_city_profit from store_sales as s1 order by branch_id; +-----------+--------------+-------------+---------------------------------+ | BRANCH_ID | STORE_PROFIT | CITY_PROFIT | STORE_PERCENTAGE_OF_CITY_PROFIT | |-----------+--------------+-------------+---------------------------------| | 1 | 10000.00 | 25000.00 | 40.00000000 | | 2 | 15000.00 | 25000.00 | 60.00000000 | | 3 | 10000.00 | 19000.00 | 52.63157900 | | 4 | 9000.00 | 19000.00 | 47.36842100 | +-----------+--------------+-------------+---------------------------------+
Postgres bietet eine so genannte Fensterfunktion namens OVER. In einer weniger natürlichen Sprache sagt man also in SQL, dass man eine Summe() über einen Datensatz haben möchte, der nach Zeit und/oder Produkt PARTITIONIERT ist.
SELECT ea_month, id, amount, ea_year, circle_id , sum(amount) OVER (PARTITION BY circle_id ORDER BY ea_year, ea_month) AS cum_amt FROM tbl ORDER BY circle_id, month;
Um tatsächlich ein YTD zu erhalten, muss das Jahr Teil der PARTITION sein, andernfalls wird die Summe über die gesamte Zeit gebildet.
Die Berechnung wird pro Zeile durchgeführt. Wenn die Tabelle also tägliche Daten enthält, die Ausgabe aber auf monatlicher Basis erfolgen soll, müssen die Daten zunächst gruppiert und für jeden Monat summiert werden, bevor eine YTD-Berechnung auf monatlicher Basis möglich ist.