views:

79

answers:

5

I have a table of weekly events that run on certain days of the week (e.g. MTWTh, MWF, etc.) and run on a certain time (e.g. 8am-5pm). What's the best way to store day of week information in MySQL to make retrieving and working with the data easiest? My CakePHP app is going to need to retrieve all events happening NOW().

For time of day, I would just use TIME. For days of the week, I had considered a 7-bit bitfield, a varchar ("MTWThFr" type deal) for the days of the week, but both of those seem like clunky solutions (the varchar being clunkier).

Any suggestions?

A: 

Since there won't be any new days of the week invented (I hope!) you could just create a bool column for each day. Then, if you are running a query to find events on a Friday, it would simply be (with a bit of pseudocode):

SELECT eventName
FROM events
WHERE fridayBool = true
AND eventStartTime < NOW()
AND eventEndTime > NOW();

In that example the name of the column you would store in an array in your code, and check today's date to see what day of the week it is, which then selects the proper name out of the array before creating the query.

Not the most elegant, but it should work.

Edit...

Example table columns:

  • eventID
  • eventName
  • eventStartTime
  • eventEndTime
  • sundayBool
  • mondayBool
  • ...
  • saturdayBool
JYelton
The one-to-many solution provided by Coov gives you an added ability of being able to change the times for each event if you want. But you might have to alter your UI accordingly because an event then may have the option of different times each day.
JYelton
+2  A: 

Can you add an DayOfWeek column in your table and make it an int? Valid values for that would be 1 thru 7. You could add a constraint on that to enforce that rule. For time, how about a BeginTime columns and an EndTime column? They would be int's as well 0-24

For an event at 5:00 pm on Monday would look like this in your table

Event_ID DayOfWeek BeginTime EndTime
1        2         1700      1800
Coov
The problem I see with this is how do you handle an event that occurs on multiple days of the week? Another entry in the same table seems like it would complicate the query.
JYelton
@jyelton it wouldn't complicate the query. You'd just get multiple rows.
Coov
Oh, true - you could just request from the table any rows that have n as the DayOfWeek to determine if the event is scheduled on that day. However, you do have the issue (or feature) of having to populate the times for the event on multiple days. The issue is the duplication of data; or the feature would be that you can have the event occur at different times on those days. Whatever suits you best.
JYelton
@Coov - I suppose if the times never varied by day, they could be moved to the parent event table, making this a pretty nice one-to-many solution.
JYelton
Coov
A: 

Why not have several lines, each line having only one column containing the day of week. This column would be just a simple :

ENUM("Monday", "Tuesday", ...)

Then, in PHP you could use date and strtotime functions to get the name of the day :

echo date('l');
echo date('l', strtotime('mon'));
// Outputs "Monday"

It is way more readable to store the name of the day.

mexique1
Storing the int value of the day of the week will save space.
Coov
Aren't ENUMs stored as ints ? On the MySQL manual page they say that ENUM values are indexed starting from 1. That is maybe why it is recommended to add values to the end of the ENUM when you alter it, to preserve the indexes. In fact I don't know...
mexique1
A: 

Break the weekly information into a separate table entirely:

events: id, beginTime, endTime, name, description
eventsbyday: id, dayofweek, event_id

This will allow you to query eventsbyday according to the current day of the week:

SELECT events.name, events.beginTime, events.endTime FROM eventsbyday JOIN events ON eventsbyday.event_id=events.id WHERE dayofweek=0

This is very rough code, but the idea is to break out the weekly information, allowing you to have the same event associated with multiple days of the week.

jshalvi
A: 

Here's a straightforward way:

EventID Title    Mon Tue Wed Thu Fri Sat Sun BeginningDate EndDate
1       MyEvent  0   0   0   1   0   0   0   14-01-2010    14-01-2033

How to use:

Simply set a 1 on the days you want to run it. Since the 7-days calendar is not likely to change any time soon, that structure should be immutable. You can choose any combination of days.

To recap:

Run every Thursdays:

EventID Title    Mon Tue Wed Thu Fri Sat Sun BeginningDate EndDate
1       MyEvent  0   0   0   1   0   0   0   14-01-2010    14-01-2033

Run every Thursdays & Mondays:

EventID Title    Mon Tue Wed Thu Fri Sat Sun BeginningDate EndDate
1       MyEvent  1   0   0   1   0   0   0   14-01-2010    14-01-2033

Further more, you get only one row per event schedule, which is easier and cleaner to handle programmatically.

For example, to find all events to be executed on monday, do:

select * from Events where Mon = 1
Wadih M.