0

完全に正規化されたテーブルを非正規化する方法について誰かアドバイスできますか? グーグルで検索してもあまり見つかりませんでした。

TableA でレコードが更新されるたびに (挿入されていませんが、今は気にする必要はありません)、変更されたフィールドの値と、それが実行されたときに関連付けられたタイムスタンプと共にレコードが HistoryOfTableA に挿入されます。

例えば。

テーブル A フィールド:

TableA_Id, FieldA, FieldB, FieldC, FieldD.... etc

HistoryOfTableA レコード:

HistID, TableA_Id, FieldChanged, OldValue, NewValue, DateCreated
1, 1, 'FieldA', 1, 2, <2013-03-18 12:20:00>
2, 1, 'FieldB', A, B, <2013-03-18 12:20:00>
3, 1, 'FieldC', A, B, <2013-03-18 12:20:00>

状況は、レポート目的でいくつかの SQL を作成しようとしています。したがって、特定の時点を指定して、それらの敵対的なテーブル エントリをまとめて、その時点での TableA のレコードの状態を把握できるようにしたいと考えています。

履歴テーブルに基づいてテーブルを作成し、作成日とテーブル A の ID を結合できると考えています

例えば。

select HistA.NewValue, 
       HistB.NewValue, 
       .... 
from FieldA_HistoryOfTableA HistA 
     inner join FieldB_HistoryOfTableA HistB on HistA.DateCreated = HistB.DateCreated
       and HistA.TableA_Id = HistB.TableA_Id 
     inner join ... etc
where HistA.FieldChanged = 'FieldA'
and HistB.FieldChanged = 'FieldB'
and .... etc...

しかし、これで私が望むすべてが得られるとは思いませんし、純粋に SQL でこれを行うことはできないかもしれません。余談ですが、TableA には 20 個のフィールドがあるため、20 個のテーブルを結合しようとするのは賢明ではないかもしれません。

4

3 に答える 3

2

あなたの問題は、テーブルが正規化されていることではなく、正規化されていないことです。

あるテーブルのフィールドによって識別されるデータは、別のテーブルのデータによって識別されるため、クエリが非常に複雑になります。

完全に正規化されたバージョンでは、フィールドもTableA別のテーブルに格納されます。

TableA
------------
TableA_Id

TableAFields
-------------
TableA_Id
FieldId
Value

Field
---------
FieldId
FieldName

HistoryOfTableA
----------------
TableA_Id
FieldId
OldValue
ChangedDate

これで、履歴テーブルのフィールドに参加できます。少しトリッキーですが、少なくとも 20 個の結合を含むクエリにはなりません。

于 2013-03-19T12:46:16.897 に答える
1

履歴テーブルから最新のレコードが必要な場合は、次の SQL を使用できます。

select ht.*
from (select ht.*,
             ROW_NUMBER() over (partition by FieldChanged, TableA_Id order by DateCreated desc) as seqnum
      from HistoryOfTableA ht
      where datecreated <= YOURDATEHERE
     ) ht
where seqnum = 1

これを単一のレコードにしたい場合は、ピボットするか集計を行う必要があります。後者のアプローチは次のとおりです。

select ht.TableA_id,
       max(case when FieldName = 'FieldA' then NewValue end) as FieldA,
       . . .
from (select ht.*,
             ROW_NUMBER() over (partition by FieldChanged, TableA_Id order by DateCreated desc) as seqnum
      from HistoryOfTableA ht
      where datecreated <= YOURDATEHERE
     ) ht
where seqnum = 1
group by TableA_id
于 2013-03-19T13:56:46.480 に答える
-1

TableA の XML 列を使用して、TableA のすべての行の履歴を記録することができます。つまり、すべての行には XML 型の列があり、その行の履歴が記録されます。次に、行をアプリケーションにプルし (行数が膨大な場合はバッチ処理で)、TableA の各レコードの履歴を見つけることができます。

于 2013-03-19T12:38:17.437 に答える