I am trying to figure out the best database design for the following;
I have individuals (stored in Agents table) that enter their billing or time worked each day for different projects. Now we have different rates that we pay based on the person and what the project is. And we also have to account for individuals getting pay cuts or raises over time. So….
I have the following tables;
Agents - table of each person
Projects - table of all projects we work
Rates - table with AgentID, ProjectID, StartDate, EndDate, Rate
Billing - table with Date, AgentID, ProjectID
So my current implementation a billing entry must be made by an agent, and I have to create a join to the rates table based on AgentID
, ProjectID
, and Date between StartDate
and EndDate
. This just seems incredibly ugly and all the billing data can be easily changed if a change were made to the rates. I'm assuming most time sheets calculate the total rate and store it in the table so it never changes unless someone specifically goes back to update the data? I'm just wondering if there is a better method for tracking this sort of data. Thanks
Best Answer
I take it that your main concern is tracking the changing rates and charging the prevailing rate when work was performed. That's not really a problem.
There is a pattern I call Temporal Normal Form. It's a way to track changing data using normalization -- a pattern we all know and love.
So the Rates table will be normalized according to static data:
and varying data:
Notice there is no
EndDate
field. The rate, once started, continues until changed. This eliminates Row Spanning Dependencies, where different fields in different rows must remain in synch.So now let's see how much a billing entry will cost the project. We're looking for the rate that was in effect on the date the hours are logged:
Notice I've added how much time is being billed to the Billing table.
This looks like a lot to get one rate, but it is a pattern and once you write it a coupla hundred times, it will sink in. It is also quite efficient.