Текущий итог по сгруппированным записям в таблице
-
22-07-2019 - |
Вопрос
У меня есть такая таблица (Oracle, 10)
Account Bookdate Amount
1 20080101 100
1 20080102 101
2 20080102 200
1 20080103 -200
...
Что мне нужно, так это новая таблица, сгруппированная по порядку учетных записей, по asc учетной записи и asc Bookdate с текущим общим полем, вот так:
Account Bookdate Amount Running_total
1 20080101 100 100
1 20080102 101 201
1 20080103 -200 1
2 20080102 200 200
...
Есть ли простой способ сделать это?
Заранее благодарю.
Решение
Вам действительно нужен дополнительный столик?
Вы можете получить нужные вам данные с помощью простого запроса, который, очевидно, можно создать в виде представления, если вы хотите, чтобы оно выглядело как таблица.
Это даст вам данные, которые вы ищете:
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
Это создаст представление, которое покажет вам данные, как если бы это была таблица:
create or replace view t2
as
select
account, bookdate, amount,
sum(amount) over (partition by account order by bookdate) running_total
from t
/
Если вам действительно нужна таблица, имеете ли вы в виду, что она должна постоянно обновляться?или только на один раз?Очевидно, что если это одноразовый вариант, вы можете просто "создать таблицу как select", используя приведенный выше запрос.
Тестовые данные, которые я использовал, следующие:
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;
Редактировать:
забыл добавить;вы указали, что хотите упорядочить таблицу - на самом деле это не имеет смысла и заставляет меня думать, что вы действительно имеете в виду, что хотели, чтобы запрос / представление - упорядочение является результатом выполняемого вами запроса, а не чем-то неотъемлемым от таблицы (игнорируя таблицы, организованные по индексу, и тому подобное).
Другие советы
Я начну с этого очень важного предостережения: НЕ создавайте таблицу для хранения этих данных. Когда вы это сделаете, вы обнаружите, что вам нужно поддерживать его, что станет постоянной болью. Напишите представление для возврата дополнительного столбца, если вы хотите это сделать. Если вы работаете с хранилищем данных, тогда может быть вы сделаете что-то подобное, но даже в этом случае вы ошибаетесь, если вы просто не можете получить необходимую производительность с индексами, достойное оборудование и т. д.
Вот запрос, который будет возвращать строки так, как вам нужно.
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
Другое возможное решение:
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
Протестируйте их обе на производительность и посмотрите, какая из них лучше для вас. Кроме того, я не проверил их полностью, кроме приведенного вами примера, поэтому обязательно протестируйте некоторые крайние случаи.
Используйте аналитику, как и в вашем последнем вопросе:
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
/
выходной сигнал:
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