有人可以建议如何对一个完全规范化的表进行非规范化吗?尽管谷歌搜索,我仍然无法找到它。
每当记录被更新(虽然没有插入,但现在不用担心)在TableA中,记录将被插入到HistoryOfTableA中,其中包含已更改的字段的值以及执行时的相关时间戳。
例如
TableA字段:
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个表可能并不明智。
答案 0 :(得分:2)
你的问题不在于表格是否正常化,而是表格不是。
由一个表中的字段标识的数据由另一个表中的数据标识,这使得查询非常复杂。
完全规范化的版本还会将TableA
中的字段存储在单独的表中:
TableA
------------
TableA_Id
TableAFields
-------------
TableA_Id
FieldId
Value
Field
---------
FieldId
FieldName
HistoryOfTableA
----------------
TableA_Id
FieldId
OldValue
ChangedDate
现在您可以加入历史记录表中的字段。这将有点棘手,但至少它不会是20个连接的查询。
答案 1 :(得分: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
答案 2 :(得分:-1)
您可以尝试使用TableA中的XML列来记录TableA中每一行的历史记录。即每行都有一个XML类型的列,并记录该行的历史记录。然后你可以将行拉入你的应用程序(如果行数很大,则以批量方式),并找出TableA中每条记录的历史记录