質問
言う、2つのテーブルがあり、1つはオブジェクトレコード用、もう1つはこれらのオブジェクトに関するアクティビティレコード用です。
オブジェクトが挿入または更新されるたびに、このアクティビティテーブルに新しいレコードを挿入します。
簡単に伝えるために、アクティビティテーブルに4つのフィールドがあると仮定します。 objectId、タイプ、ステータス、日付。
オブジェクトが更新されようとしているとき、オブジェクトの最後の状態を取得して変更を探す予定です。更新値と前の値に差がある場合、新しい入力で値を設定します。それ以外の場合は、nullを設定します。したがって、たとえば更新プロセスでは、ユーザーはオブジェクトのステータス値のみを変更しますが、タイプ値は同じままにします。そのため、タイプにnull値、ステータスに新しい値を持つ新しい行を挿入します。
SELECT * FROM Activity; oid type status date ----------------------------------------- 1 0 1 2009.03.05 17:58:07 1 null 2 2009.03.06 07:00:00 1 1 null 2009.03.07 20:18:07 1 3 null 2009.03.08 07:00:00
したがって、オブジェクトの現在の状態を示すビューを作成する必要があります
SELECT * FROM ObjectStateView Where oid = 1; oid type status date ----------------------------------------- 1 3 2 2009.03.08 07:00:00
どうすればこれを達成できますか?
解決
日付を使用して最新のレコードを見つけることができます:
CREATE VIEW foo
AS
SELECT
A.oid,
(SELECT TOP 1 type FROM Activity At WHERE At.OID = A.oid AND At.Date <= MAX(A.date) AND type IS NOT NULL),
(SELECT TOP 1 status FROM Activity Ast WHERE Ast.OID = A.oid AND Ast.Date <= MAX(A.date) AND status IS NOT NULL),
MAX(A.date) AS date
FROM
Activity A
GO
編集:JOIN(テストなし)が必要な場合
CREATE VIEW foo
AS
SELECT TOP 1
A.oid,
At.type,
Ast.status,
A.date
FROM
Activity A
LEFT JOIN
(SELECT TOP 1 oid, date, type FROM Activity WHERE type IS NOT NULL ORDER BY date DESC) At ON A.OID = At.oid
LEFT JOIN
(SELECT TOP 1 oid, date, status FROM Activity WHERE status IS NOT NULL ORDER BY date DESC) Ast ON A.OID = Ast.oid
ORDER BY date DESC
GO
これを以前に追加しておくべきでした:
テーブルに11回タッチする必要があるため、指数関数的にスケーリングします。
より良い解決策は、「現在」を維持することです。アクティビティのトリガーを介してテーブルとメンテナンスを行います。
他のヒント
MAX 関数の使用を検討しましたか?
select oid, type, status, MAX(date) as max_date
from ObjectStateView
where oid = 1
そこにnullが必要な理由がよくわかりません。最新のエントリを前のエントリと比較することにより、入力間で何が変更されたかを追跡できます。オブジェクトの現在の状態は、テーブル内の最新のエントリです。オブジェクトの変更を追跡するオブジェクトの部分のハッシュを作成し、それを追加の列として保存することにより、オブジェクトが変更されたかどうかを判断できます。
履歴値:
変更を追跡するので、オブジェクトのステータスを履歴で確認することもできます。
SELECT a.oid,
a.date,
a_type.type,
a_status.status
FROM Activity a
LEFT JOIN Activity a_type
ON a_type.oid = a.oid
AND a_type.date = (SELECT TOP 1 date FROM Activity WHERE oid = a.oid AND date <= a.date AND type IS NOT NULL ORDER BY date DESC)
LEFT JOIN Activity a_status
ON a_status.oid = a.oid
AND a_status.date = (SELECT TOP 1 date FROM Activity where oid = a.oid AND date <= a.date AND status IS NOT NULL ORDER BY date DESC)
返される値:
oid date type status
----------- ---------- ----------- -----------
1 2009-03-05 0 1
1 2009-03-06 0 2
1 2009-03-07 1 2
1 2009-03-08 3 2
パフォーマンスの考慮事項:
一方、フィールドがいくつかあり、テーブルが大きい場合、パフォーマンスが問題になります。この場合、別のテーブル MyDataHistory に値全体を格納/キャッシュすることも意味があります。このテーブルには、上記の表のようなデータが含まれます。次に、最新の行(1行のみ)をOIDと日付でフィルタリングするSQLビューを使用して、現在の(最新の)バージョンを選択するのは簡単です。