1

3つのテーブルがあり、それらに関連する列は次のとおりです。

tPerson
-> PersonID

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

Status
-> StatusID

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

現在のステータスを取得するためのクエリ:

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

私が欲しいのは、クエリの列として最新のStatusIDを含むPersonレコードのリストを取得するクエリです。

次のアプローチを試しました。

  1. 上記のクエリをサブクエリとしてselectに含めます。
  2. CurrentPersonStatusHistoryID列をtPersonテーブルに追加し、User-Defined-Functionを呼び出す計算列を使用してそれを維持します。
  3. tPersonStatusHistoryテーブルのトリガーを使用してCurrentPersonStatusHistoryID列を維持します。

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

トリガーを維持するのは難しいので、それらから離れたいと思います。また、Insert-Select、または複数のレコードを含むUpdateクエリを実行する場合、トリガーは最初のレコードでのみ呼び出され、他のレコードでは呼び出されないこともわかりました。

私が本当に望んでいるのは、CurrentPersonStatusHistoryIDの列定義にロジックを入れ、[保存]を押して、介入なしでバックグラウンドで永続化および更新することです。

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

4

1 に答える 1

1

別のアプローチは、おそらくビューとして、次のクエリのようなものを使用することです。各個人の最新の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

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

于 2012-05-03T00:50:43.047 に答える