Can anyone advise on how to go about denormalising a fully normalised table? I've not been able to find much on it despite googling.
Whenever a record is updated (though not inserted, but lets not worry about that now) in TableA a record is inserted into HistoryOfTableA with the values of the fields which have changed and an associated timestamp when it was carried out.
eg.
TableA fields:
TableA_Id, FieldA, FieldB, FieldC, FieldD.... etc
HistoryOfTableA records:
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>
The situation is I'm looking to create some SQL for reporting purposes. So I want to be able to specify a point in time, and be able pull together those hostory table entries and work out what the state of that record from TableA was at that time.
I'm thinking I can create tables based on the history table and joined on the date created and the Id from table A
eg.
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...
But I don't think this is going to give me all that I want and I may not be able to do this purely in SQL. As an aside there are 20 fields in TableA so trying to join 20 tables may not be wise.
You can try using a XML column in the TableA to record the history of every row in TableA. i.e. Every row has a column which is of type XML and records the history of that row. Then you can pull the rows into your application(in a batched manner if the number of rows are huge), and find out the history of each record in TableA
Your problem is not that the table is normalised, but rather that it isn't.
The data identified by fields in one table is identified by data in another table, which makes it very complicated to query.
A fully normalised version would also store the fields from
TableA
in a separate table:Now you can join in the fields from the history table. That will be a bit tricky, but at least it won't be a query with 20 joins.
If you want the most recent records from the history table, you can use the following SQL:
If you want this as a single record, you should either pivot or do an aggregation. Here is the latter approach: