0

非常に単純な SQL 要件がありますが、パフォーマンスの問題が発生しているため、以下のシナリオの「ベスト プラクティス」を知りたいと考えています。

私はチームのリストを持っています。これらのチームは毎週/ラウンドにゲーム料金を支払います。チームが支払いを行わない場合、未払いの残高があります。すべてのチームの支払いは、ますます大きくなっている支払いテーブルに入ります。チームのリストと現在の残高を返すベスト プラクティスは何ですか?

私が現時点で持っているもの:

Select teams.*, (Select SUM(amount) from payments p where p.TeamID=teams.TeamID) as teambalance 
from (select TeamID, TeamName from Teams) teams
4

4 に答える 4

2

私はこれについてよく考えましたが、「同じ情報を 2 回保存しないでください」という古典的なアドバイスはここで間違っているか、少なくとも誤解されていると思います。

銀行がそれをどのように行う必要があるかを考えてください。明らかに、現在の残高を知りたい場合、20 年間顧客である場合、現在の残高を見つけるために 20 年間のアカウント アクティビティを合計することはありません。それを踏まえて、私はそれを処理する2つの方法を考えています。

  1. 「クローズ」する期間を選択し、常に最後にクローズした期間から計算します。これにより、合計が比較的短く保たれます。毎月の明細書は、おそらくそのような良いアンカーです。追跡する同様の自然な期間またはビジネス ライフ サイクルはありますか?
  2. アカウントの履歴を現在に固定することで、さかのぼって作業します。0 から開始して追加する代わりに、現在の残高から開始して戻ります。私の意見では、これは同じように有効であり、古い履歴を削除したいときに何もする必要がないという追加の利点があります。現在の残高を保存し、想定される非正規化を忘れます。現在の残高は、開始時の残高と同様に経験的な事実であり、このようにアカウントを固定しても問題はありません。

パフォーマンスが問題ない限り、必要に応じて追加を続けることができます。しかし、それは最適ではないかもしれません。

現在のクエリは問題ありませんが、teams派生テーブルは必要ありません。MySQL を使用していない限り、DBMS はこの種の「ヘルプ」を必要としませんが、MySQL は実際に害を受ける可能性があります。

于 2012-08-05T07:57:21.780 に答える
1
select teamId,teamName,sum(amount)
from teams t join payments p on t.teamId = p.teamId
group by t.teamId, t.teamName
于 2012-08-05T05:33:21.840 に答える
0

このタスクを達成するために 2 つの方法を使用しました。1 つは、現在使用している方法です。もう1つはクロス適用を使用しています。

私はあなたの現在の方法を好む -

于 2012-08-05T05:30:45.427 に答える
0

これは、SELECT 句 (または結合) でサブクエリを使用するよりも高速な場合があります。

select teams.TeamID, teams.teamName, team_balances.teambalance
  from teams
  join ( select TeamID, sum(amount) teambalance
           from payments
         group by TeamID
  ) team_balances
  on team_balances.TeamID = teams.TeamID;

これにより、N 回のインデックス スキャン (チームごとに 1 回) を実行するのではなく、支払いテーブルを 1 回連続してスキャンします。

非正規化

別のオプションは、「outstanding_balance」列をチーム テーブルに追加することです。

支払いテーブルにトリガーを作成します。トリガーで、TeamID と請求書/支払い額に基づいて、チームのoutside_balance 列をそれぞれインクリメントまたはデクリメントします。

RDBMS によっては、マテリアライズド ビューを使用することもできます。これは、各チームの残高が別のテーブルに格納される点を除いて、トリガー メソッドと似ています。

于 2012-08-05T08:04:24.007 に答える