Best way to store weekly event in MySQL? - mysql

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?

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

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

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.

In case anyone coming this way again I am using SMTWHFA quite efectively with a simple string search.
So Monday Wednesday Friday would be MWF and Sunday Monday Thursday would be SMH. Takes a while to get used to H=Thursday (second letter) and Saturday=A but it works!

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

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.

Related

How to design table structure for Operating Hours

Problem #1:
How can the table be designed in MySQL in efficient way to structure
1) Store Opening Time,
2) Break Time and
3) Closing Time in a day
For an instance, On Sunday: Opening Time: 7:00AM, Closing Time: 5:00PM, Break Time Start: 1:00PM, Break Time End: 2:30PM.
Problem #2:
How to define the query to search that table for all Stores that are being Opened/Closed between the given range.
For an instance, If user tries to filter the stores for Opening between 9:00AM and 12:00AM. How can I apply query for this filter since it might be possible the Break Time or Closing Time could be within that timeframe.
store_id day open_time break_start break_end close_time
1 mon 7:00AM 1:00PM 2:30PM 5:00PM
1 tue 7:00AM 1:00PM 2:30PM 5:00PM
1 wed 7:00AM 1:00PM 2:30PM 5:00PM
1 thu 7:00AM 1:00PM 2:30PM 5:00PM
1 fri 7:00AM 1:00PM 2:30PM 5:00PM
1 sat Closed
1 sun Closed
Something similar to this. If the user uses criteria: Open Time between: 8:00AM to 2:00PM; to search the store then He must be able to see all the stores that are opened during that timeframe. This timeframe must also include with store open_time. That is, based on criteria provided, the store is Open at 7:00AM, 8:00AM and 9:00AM and until 2:PM.
Better to create three different columns, since you want to query between
Opening time , closing time or break time
create table store_timing
(
store_id int, -- from store table
Opening_Time datetime,
break_time datetime,
closing_time datetime
)
Query :
select *
from store_timing
where Opening_Time<= 'Opening_Time'
and closing_time <= 'closing_time'

MYSQL: Inserting time period OR time/moment

I want to build a little calendar system for my website.
When the user creates an appointment he can choose between a time period (like 3rd march to 7th march) and a concrete day with time/moment (like 3rd march 2016 11:00).
I want to insert this into the mysql database.
Values for inserting a time period:
date1: 3rd march 2016
date2: 7th march 2016
Values for inserting a concrete day with time:
datetime: 3rd march 2016 11:00
Now the question I stuck on: How should the table look like?
I thought on sth like this (only the columns):
id | appointment | date1 | date2 | datetime1
And when the user inserts a time period the datetime-field would be empty. But is this the way to go?
One way would be
id
appointment
startdate
starttime (empty if it is an entry for a whole day)
enddate (empty if it is a single entry without a period)
endtime (empty if it is an entry for a whole day)

MySQL custom datetime

I am trying to display data associated with date. However in my case, I don't want the date to start at 00:00:00 and finishes at 23:59:59. Rather I want it to start at 16:00:00 and finishes at 06:00:00 the next day. In other words I want to create a custom time for date.
In the same time I want to GROUP_BY date.
For instance I have these values in the database:
want it to give me:
date: 2013-09-08 count: 2
date: 2013-09-09 count: 1
I am not asking for code, but a way to think about it, or useful methods.
Thank you in advance!
The simplest method is to take the existing date and subtract six hours to get the "effective" date. You would do this for output purposes only.
Example:
select date(datecol - interval 6 hour) as MyDate, count(*)
from t
group by date(datecol - interval 6 hour);
You can use a where clause to remove the times between 6:00 and 16:00 (unless that is a typo).

My SQL query to list dates that have no records

I have an online calendar system that I use for tracking my band's gigs - I'd like to construct a query that will display all Fridays and Saturdays that don't currently have a record assigned to them.
eg,
if I have a record in the DB for Friday 23rd Aug and Friday 30th Aug (records being gigs that are booked), what would the query cirteria be to output Saturday 24th Aug (as it has no record)?
Select * from ['giglist']
where ['gigdate'is in 'friday','saturday']
and ['gigdate' doesn't have a record]
I will probably set the days of the week as variables so that the user can run the query for any day or selection of days.
Thanks,
Darren
if assuming from your question there is a field gigdate of date type that keeps date information and a seperate record field.
Then query would be,
select DAYNAME(gigdate), DAYOFMONTH(gigdate), MONTHNAME(gigdate) from giglist where
DAYNAME(gigdate) in ('Friday', 'Saturday') and
recordfield is NULL;
It's better to use single date type field and just store date only, as mysql has powerful set of date functions to help you out for your needs.

Calculate yearly expiry in MySQL from static date

This might be simple but my brain has melted after a long day of non stop coding, and I'm running out of paper fast...
I'm trying to figure out a yearly expiry formula to calculate in a stored procedure.
Simplified table:
Security_Table
-----------------
User_ID [int]
Join_Date [DateTime]
Expired [VARCHAR]
So if a user joined on 2010-01-11 Expired would update to "TRUE" today, same goes for someone who joined on 2009-01-11 as it's a recurring expiry.
I'm running the procedure on a daily basis through scheduled tasks, would comparing the day and month be suffice? Obviously accounting for a leap year.
UPDATE Security_Table SET Expired = 'TRUE' WHERE DATE_FORMAT(Join_Date,'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
Thanks guys.
Yes, you can use WHERE month = month and date = date. (Though be careful of 29th Feb as a join date.)
This does, however, mean you have to scan to whole table/index looking for matches. If you have a large table, this may be a problem.
I would think that in this case you're better off setting an expiry date value. Then checking that...
WHERE
expiry_date <= CURDATE()
When some-one renews you can update the expiry. SET expiry_date = DATE_ADD(expiry_date, INTERVAL 1 YEAR). You may have a new offer for 13 months for the price of 12, and setting the expiry lets you be flexible like that. It's even immune to the 29th Feb problem. In terms of reliability; if your batch process fails, running it a day late won't make you miss a bunch of people...
This query will simply check the Month and Day of every Join_Date against today, If you joined on Feb 29th, it will expire on Feb 28th or it will take 4 years to expire.
UPDATE Security_Table
SET Expired='TRUE'
WHERE Expired='FALSE'
AND
(
(DATE_FORMAT(Join_Date,'%m-%d')='02-29' AND DATE_FORMAT(NOW(),'%m-%d')='02-28')
OR
(DATE_FORMAT(Join_Date,'%m-%d') = DATE_FORMAT(NOW(),'%m-%d'))
);
You should also index the table so that only those records that have Expired='FALSE' are examined.
ALTER TABLE Security_Table ADD INDEX (Expired,Join_Date);
Give it a Try !!!