Laufende Summe von gruppiert Datensätze in der Tabelle
-
22-07-2019 - |
Frage
Ich habe eine Tabelle wie diese (Oracle, 10)
Account Bookdate Amount
1 20080101 100
1 20080102 101
2 20080102 200
1 20080103 -200
...
Was ich brauche, ist neue Tabelle nach Konto, um nach Konto asc und Bookdate asc mit einem laufenden Gesamtfeld gruppiert, wie folgt aus:
Account Bookdate Amount Running_total
1 20080101 100 100
1 20080102 101 201
1 20080103 -200 1
2 20080102 200 200
...
Gibt es eine einfache Möglichkeit, es zu tun?
Vielen Dank im Voraus.
Lösung
Haben Sie wirklich brauchen die zusätzliche Tabelle?
Sie können diese Daten erhalten Sie mit einer einfachen Abfrage benötigen, die Sie als Ansicht offensichtlich schaffen können, wenn man es wie eine Tabelle angezeigt werden sollen.
Diese erhalten Sie die Daten, die Sie suchen:
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
Dies wird eine Ansicht zu erstellen, um die Daten zu zeigen, als ob es sich um eine Tabelle waren:
create or replace view t2
as
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
Wenn Sie wirklich die Tabelle benötigen, meinen Sie, dass Sie es ständig aktualisiert müssen? oder einfach nur ein einmaliger? Natürlich, wenn es sich um eine aus ist kann man einfach „create table as select“, um die obige Abfrage verwendet wird.
Die Testdaten I verwendet wird:
create table t(account number, bookdate date, amount number);
insert into t(account, bookdate, amount) values (1, to_date('20080101', 'yyyymmdd'), 100);
insert into t(account, bookdate, amount) values (1, to_date('20080102', 'yyyymmdd'), 101);
insert into t(account, bookdate, amount) values (1, to_date('20080103', 'yyyymmdd'), -200);
insert into t(account, bookdate, amount) values (2, to_date('20080102', 'yyyymmdd'), 200);
commit;
edit:
hat vergessen, hinzuzufügen; Sie angegeben haben, dass Sie die Tabelle bestellt werden wollte - dieses Gefühl nicht wirklich machen, und lässt mich denken, dass Sie wirklich bedeuten, dass Sie die Abfrage / Ansicht wollte - Bestellung ist ein Ergebnis der Abfrage Sie, nicht etwas auszuführen, die inherant ist in die Tabelle (Tabellen Index Organized und dergleichen zu ignorieren).
Andere Tipps
Ich werde mit dieser sehr wichtigen caveate beginnen: Erstellen Sie keine Tabelle, um diese Daten zu halten. Wenn Sie tun, werden Sie feststellen, dass Sie es zu halten brauchen, die eine nie endende Kopfschmerzen werden wird. Schreiben Sie eine Ansicht, die die zusätzliche Spalte zurück, wenn Sie das tun wollen. Wenn Sie mit einem Data-Warehouse arbeiten dann vielleicht Sie würde so etwas tun, aber auch dann auf der Seite einer Ansicht irren, wenn Sie einfach nicht die Leistung erhalten können, die Sie mit Indizes benötigen, anständige Hardware, etc.
Hier ist eine Abfrage, die die Reihen den Weg zurückkehren, die sie gebraucht werden.
SELECT
Account,
Bookdate,
Amount,
(
SELECT SUM(Amount)
FROM My_Table T2
WHERE T2.Account = T1.Account
AND T2.Bookdate <= T1.Bookdate
) AS Running_Total
FROM
My_Table T1
Eine andere mögliche Lösung ist:
SELECT
T1.Account,
T1.Bookdate,
T1.Amount,
SUM(T2.Amount)
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON
T2.Account = T1.Account AND
T2.Bookdate <= T1.Bookdate
GROUP BY
T1.Account,
T1.Bookdate,
T1.Amount
Testen Sie sowohl für die Leistung und sehen, welche für Sie besser funktioniert. Auch ich habe nicht gründlich getestet sie über das Beispiel, das Sie gab, so sicher sein, einige Grenzfälle zu prüfen.
Mit Analysen, wie in Ihrer letzten Frage:
create table accounts
( account number(10)
, bookdate date
, amount number(10)
);
delete accounts;
insert into accounts values (1,to_date('20080101','yyyymmdd'),100);
insert into accounts values (1,to_date('20080102','yyyymmdd'),101);
insert into accounts values (2,to_date('20080102','yyyymmdd'),200);
insert into accounts values (1,to_date('20080103','yyyymmdd'),-200);
commit;
select account
, bookdate
, amount
, sum(amount) over (partition by account order by bookdate asc) running_total
from accounts
order by account,bookdate asc
/
Ausgabe:
ACCOUNT BOOKDATE AMOUNT RUNNING_TOTAL
---------- -------- ---------- -------------
1 01-01-08 100 100
1 02-01-08 101 201
1 03-01-08 -200 1
2 02-01-08 200 200