Pregunta

Tengo una tabla como esta (Oracle, 10)

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

Lo que necesito es una nueva tabla agrupada por orden de cuenta por asc de cuenta y asc de Bookdate con un campo de total acumulado, como este:

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

¿Hay una manera simple de hacerlo?

Gracias de antemano.

¿Fue útil?

Solución

¿Realmente necesitas la mesa extra?

Puede obtener los datos que necesita con una simple consulta, que obviamente puede crear como una vista si desea que aparezca como una tabla.

Esto le dará los datos que está buscando:

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

Esto creará una vista para mostrarle los datos como si fuera una tabla:

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

Si realmente necesita la tabla, ¿quiere decir que la necesita constantemente actualizada? o solo uno fuera? Obviamente, si es único, simplemente puede "crear una tabla como seleccionar" utilizando la consulta anterior.

Los datos de prueba que utilicé son:

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;

editar:

olvidé agregar; especificó que deseaba que se ordenara la tabla, esto realmente no tiene sentido, y me hace pensar que realmente quiere decir que deseaba la consulta / vista, el pedido es el resultado de la consulta que ejecuta, no es algo que no está vigente en la tabla (ignorando las tablas organizadas de índice y similares).

Otros consejos

Comenzaré con esta advertencia muy importante: NO cree una tabla para contener estos datos. Cuando lo haga, encontrará que necesita mantenerlo, lo que se convertirá en un dolor de cabeza interminable. Escriba una vista para devolver la columna adicional si desea hacerlo. Si está trabajando con un almacén de datos, entonces tal vez haría algo como esto, pero aun así se equivocaría al lado de una vista a menos que simplemente no pueda obtener el rendimiento que necesita con los índices, hardware decente, etc.

Aquí hay una consulta que devolverá las filas de la forma en que las necesita.

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

Otra posible solución es:

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

Probar el rendimiento de ambos y ver cuál funciona mejor para usted. Además, no los he probado a fondo más allá del ejemplo que usted dio, así que asegúrese de probar algunos casos extremos.

Use análisis, como en su última pregunta:

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
/

salida:

   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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top