I have created a table for customer bills, and a table for customer profiles which contains rates associated with them specifically. The problem is that after a new rate change has been imposed I want to be able to look at an old bill, via a report, and have it reflect the "old" rate within proper historical context. I'm looking for suggestions on how to best manage ongoing rate changes while maintaining a billing rate history in my reports?
Personal design opinion set against relational theory is always an interesting one. I offer my opinion... you make up your own mind inevitably.
As with any 'rate' or item of data that has a 'point in time' relevance to it the principle is to capture that item of data and store it in a place that can reflect that data correctly and accurately.
If we have a record that deals with a sale then the 'rate at the time of the sale' in my view should be stored with the sale record. The sale record as a whole should logically have a date time stamp for its placement in any stack of records. Any calculations can then be conducted against the 'rate' stored in the sale row as it reflects the rate that was
relevant at the time.
It could be argued of course that the previous paragraph breaks the relational model by denormalising the rate in that you could store a single rate and a date change in a separate tblRates table and store an ID or other reference to reference the 'rate change'
There is merit in this argument, but in my view can become a little inhibiting and potentially unnecessarily complex. If we look at the principle of
'performance versus overhead' for a moment within the context of system build the purpose of any build is to provide a database that is effective in terms of speed without compromising integrity of data. Provided we do that, then for me the practical benefits outweigh the purist theory.
To retrieve anything that needs 'looking up' from a separate table requires a
JOIN of some sort, for instance from a table we might define as tblRates (a table storing rate value lookups).
No problem you might think in essence..... but over the lifetime of your application it is one
LESS join to contend with in the case of subsequent unforeseen and potentially complex SQL queries that you might have to build at some point.
You can query the specific rates themselves by reference to an datetime field that you might use to 'time stamp' the record and/or customerid/orderid/saleid ie:
"What dates do we have for rate changes for this customer" or
"for a rate of 17.5 what customers have been given this rate between a certain time and date period." All of this can be queried with a simple SELECT statement against the single sales table which if indexed properly will also provide for swiftness it terms of response times and sorting.
There is nothing of course to prevent storing default 'new' values a rate 'AS of now' in a separate lookup table as it applies to individual customers or indeed basing new records on some calculated value ie: one that maybe determine the 'importance' level or the 'value worth' of a customer 'as of now' so to speak.
These new values obviously append to any new sales row and become history the very second they become so appended.
Regards
Jim :)