 <p>Store the schedule as an iCalendar <a href="http://stackoverflow.com/questions/tagged/rrule?sort=votes">rrule</a> (or a more normalized version if your prefer). </p> <p>Create a function to return upcoming dates for the rule. </p> <p>Create a materialized view of upcoming dates if you need to, to boost performance. </p> <p><a href="http://repo.or.cz/w/davical.git?a=blob;f=dba/rrule_functions.sql;hb=HEAD" rel="nofollow">PostgreSQL Functions for RRULE handling</a></p> <p>Use Table Inheritance to model the geographical locations. You should consider City to be a child of State and not County, as some cities <em>contain</em> counties. </p> <p>You want to be able point a single foreign key at an abstract geographical location such as "Ohio" or "Cuyahoga County, Ohio"</p> <p>Use a junction table to map multiple locations to a campaign.</p> <pre><code>--postgresql syntax create table campaigns ( campaign_id int primary key, name text unique, rrule text not null check ( is_valid_rrule(rrule) ) --you would need to write this ); create table locations ( location_id int primary key, type text not null check ( type in ('COUNTRY', 'PRIMARY_DIVISION','SECONDARY_DIVISION') ), --use a lookup table in real life name text not null, parent_id int null references locations (location_id) check ( type = 'COUNTRY' or parent_id is not null), unique (name, parent_id) ); create table campaign_locations ( campaign_id int references campaigns(campaign_id), location_id int references locations(location_id), primary key (campaign_id, location_id) ); --insert some locations: insert into locations values (1, 'COUNTRY', 'United States of America', null), (2, 'PRIMARY_DIVISION', 'Ohio', 1), (3, 'SECONDARY_DIVISION', 'Cuyahoga County', 2), (4, 'SECONDARY_DIVISION', 'Adams County', 2); --create a campaign with a recurrence rule: insert into campaigns values (1, 'My Campaign', 'FREQ=WEEKLY;BYDAY=MO,WE'); --associate a campaign with Cuyahoga and Adams counties: insert into campaign_locations values (1, 3), (1, 4); </code></pre>