2012-05-03 18 views
1

は、私は3つのテーブルを持って参加し、及びその関連する列は、以下のとおりです。最善の方法は、多対多

tPerson 
-> PersonID 

tPersonStatusHistory 
-> PersonStatusHistoryID 
-> PersonID 
-> StatusID 
-> PersonStatusDate 

Status 
-> StatusID 

は私が人が今まで持っていたことを、すべてのステータスの完全な履歴を保存したいです。しかし、私はまた、現在の状態に簡単にアクセスしたい。現在の状態を取得する

問合せ:私が欲しいもの

SELECT TOP 1 StatusID FROM tPersonStatusHistory 
WHERE PersonID = ? ORDER BY PersonStatusDate DESC 

は、クエリ内の列として、最新のStatusIDで、私の個人レコードのリストを取得しますクエリです。選択中のサブクエリとして上記のクエリを含む

  1. は、我々は以下のアプローチを試してみました。

  2. CurrentPersonStatusHistoryID列をtPerson表に追加し、ユーザー定義関数を呼び出す計算列を使用してその列を維持します。
  3. tPersonStatusHistoryテーブルのトリガを使用してCurrentPersonStatusHistoryID列をメンテナンスします。

Personレコードをプルアップするためのクエリは非常に高いので、毎回Historyテーブルを検索する必要はありません。トリガー・アプローチは、データがPerson表に永続化され、更新が行われたときにのみ変更されるため(これはあまり頻繁ではありません)、私が望むものに最も近いものです。

私はトリガーを維持することが難しいと私は彼らから離れて滞在することをお勧めします。また、複数のレコードを含むInsert-SelectまたはUpdateクエリを実行すると、トリガは最初のレコードでのみ呼び出され、他のレコードでは呼び出されないことがわかりました。

私が本当に望むのは、CurrentPersonStatusHistoryIDの列定義にいくつかのロジックを入れてSaveを押し、自分の介入なしに舞台裏で永続化して更新することです。

多対多の関係が一般的であることを考えると、他の誰かが同様の状況に遭遇したかどうかと、これを実装する方法の中で最高のパフォーマンス、できれば最も簡単な方法についての洞察がありますか?

答えて

1

もう1つのアプローチは、おそらくビューとして次のようなものを使用することです。それはあなたに各Personの最新のStatusIDを与えます。

SELECT PersonID, StatusID 
FROM (
    SELECT PersonID, StatusID, 
     rank() OVER(PARTITION BY PersonID ORDER BY PersonStatusDate DESC) as rnk 
    FROM tPersonStatusHistory 
) A 
WHERE rnk = 1 

これはパフォーマンスに関する要件を満たしているかどうかはわかりませんが、あなたが調べることのできるものです。

+0

私はこれまで一度も見たことがありません、ありがとうございます。それは確かに他の方法よりもきれいに見えます。私はこれをビューに変えて、テーブルの代わりにテーブルに参加し、私がどうやって行くのか見てみましょう。 –

関連する問題