Domanda

Ho una tabella come questa (Oracle, 10)

Account     Bookdate     Amount
      1     20080101        100
      1     20080102        101
      2     20080102        200
      1     20080103       -200
...

Ciò di cui ho bisogno è una nuova tabella raggruppata per Ordine account in base all'account asc e Bookdate asc con un campo totale parziale, come questo:

Account     Bookdate     Amount     Running_total
      1     20080101        100               100
      1     20080102        101               201
      1     20080103       -200                 1
      2     20080102        200               200
...

C'è un modo semplice per farlo?

Grazie in anticipo.

È stato utile?

Soluzione

Hai davvero bisogno del tavolo extra?

Puoi ottenere quei dati di cui hai bisogno con una semplice query, che puoi ovviamente creare come vista se vuoi che appaia come una tabella.

Questo ti darà i dati che stai cercando:

select 
    account, bookdate, amount, 
    sum(amount) over (partition by account order by bookdate) running_total
from t
/

Questo creerà una vista per mostrarti i dati come se fosse una tabella:

create or replace view t2
as
select 
    account, bookdate, amount, 
    sum(amount) over (partition by account order by bookdate) running_total 
from t
/

Se hai davvero bisogno della tabella, vuoi dire che ti serve costantemente aggiornata? o solo uno uno? Ovviamente se è una tantum puoi semplicemente " creare una tabella come selezionare " utilizzando la query sopra.

I dati di test che ho usato sono:

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;

modifica:

dimenticato di aggiungere; hai specificato che volevi ordinare la tabella - questo non ha davvero senso, e mi fa pensare che intendi davvero che volevi la query / vista - l'ordinamento è il risultato della query che esegui, non qualcosa che è inerente a la tabella (ignorando le tabelle organizzate dall'indice e simili).

Altri suggerimenti

Inizierò con questo caveato molto importante: NON creare una tabella per contenere questi dati. Quando lo fai scoprirai che è necessario mantenerlo che diventerà un mal di testa senza fine. Scrivi una vista per restituire la colonna aggiuntiva se vuoi farlo. Se stai lavorando con un data warehouse allora forse faresti qualcosa del genere, ma anche in questo caso sbaglierai sul lato di una vista a meno che tu non riesca semplicemente a ottenere il rendimento di cui hai bisogno con gli indici, hardware decente, ecc.

Ecco una query che restituirà le righe nel modo in cui ne hai bisogno.

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

Un'altra possibile soluzione è:

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

Provali entrambi per le prestazioni e vedi quale funziona meglio per te. Inoltre, non li ho testati accuratamente oltre l'esempio che hai fornito, quindi assicurati di testare alcuni casi limite.

Usa le analisi, proprio come nella tua ultima domanda:

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
/

uscita:

   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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top