I have a problem in which I need to track actual sales against a sales goal for a “Period”. A Period can be a day, month, quarter or year.
Initially, I have come up with an enum for PeriodType (1-4, Day, Month, Quarter, Year respectively). Given this, I would need 3 values to uniquely describe a Period: 1) a PeriodType, 2) an integer for a PeriodYear (eg. 2010, 2011, etc.) and 3) an integer for a PeriodNumber.
So, for instance, {1,2011,38} would be the day February 2, 2011. Or, {3,2,2010} would be the second quarter of 2010. Or {2,4,2012} would be the month of April, 2012.
Having an object that exposes these three properties is not a problem. But in terms of the database, I am trying to figure out how to store the relationship of an entity (like a Goal or a Sale) to a Period – it doesn’t seem very elegant to have 3 columns in every table that requires a Period relationship. One way would be to have a table for Period that has a primary key and the other 3 values – but it doesn’t make sense to persist the Period itself like that because it is a time concept that can be calculated.
What would be the best way to represent my definition of a “Period” with a single unique value? Or is my definition of a Period misguided and there is a simpler way to do the same thing?
The simplest solution would be to store Sales against the lowest level of granularity, i.e. a day. In would then be a simple matter to aggregate those sales for goals which track sales at a longer period.
If this does not meet your requirements you should explain in a bit more detail how the data is gathered and used, with a specific focus on why you need a more complicated data structure.
The question of timezones is problematic but not a showstopper. The important thing is to agree on a single point of truth for time, which ought to be the database, and hold all date times in UTC. Clients would have to translate UTC into their timezone when retrieving data and vice versa when saving it.
How easy this is in practice depends very much on your flavour of database, but pretty much every RDBMS ought to support this functionality.