12

このようなテーブルがあります(Oracle、10)

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

私が必要としているのは、Account asc と Bookdate asc による Account order でグループ化された新しいテーブルで、次のような累計フィールドがあります。

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

それを行う簡単な方法はありますか?

前もって感謝します。

4

3 に答える 3

20

余分なテーブルは本当に必要ですか?

簡単なクエリで必要なデータを取得できます。テーブルのように表示したい場合は、明らかにビューとして作成できます。

これにより、探しているデータが取得されます。

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
/

テーブルが本当に必要な場合は、常に更新する必要があるということですか? それともワンオフ?明らかに、それが1回限りの場合は、上記のクエリを使用して「選択としてテーブルを作成」​​できます。

私が使用したテストデータは次のとおりです。

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;

編集:

追加するのを忘れました。テーブルを順序付けすることを指定しました-これは実際には意味がありません。クエリ/ビューが必要だったということを本当に意味していると思います-順序付けは、実行したクエリの結果であり、継承されたものではありませんテーブル (インデックス構成テーブルなどは無視)。

于 2009-01-13T15:33:00.530 に答える
4

この非常に重要な警告から始めます。このデータを保持するテーブルを作成しないでください。あなたがそうするとき、あなたはそれを維持する必要があり、それは終わりのない頭痛になるでしょう. 必要に応じて、余分な列を返すビューを作成します。データ ウェアハウスを使用している場合は、このようなことをするかもしれませんが、それでも、インデックスやまともなハードウェアなどで必要なパフォーマンスが得られない場合を除き、ビューの側でエラーを起こします。

必要な方法で行を返すクエリを次に示します。

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

両方のパフォーマンスをテストして、どちらがより適切に機能するかを確認してください。また、私はあなたが与えた例を超えてそれらを完全にテストしていないので、必ずいくつかのエッジケースをテストしてください.

于 2009-01-13T15:25:58.127 に答える
4

最後の質問と同じように、分析を使用してください。

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
于 2009-01-13T15:34:24.333 に答える