Improving my current database design to store employees' schedules - php

I need to come up with a software able to store employees' schedules in a database. I currently have this design:
CREATE TABLE IF NOT EXISTS `schedules` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`employee_id` varchar(32) NOT NULL,
`day_of_week` int(2) NOT NULL,
`starting_time` time DEFAULT NULL,
`ending_time` time DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Pretty straight forward. Print today's date, figure out what is the day of the week, and retrieve all matches from database, but I'd like to know a better way to achieve the same thing.
I need to display on a calendar employees' schedules and I need to pass a date to the calendar in order to be displayed. However, I cannot pass a date to the calendar if the only information I know is that a given employee is going to work on Wednesday.
Given the latter database design, is there a way to retrieve all the Wednesdays, or Mondays of a month/year?
Thank you!
EDIT
I need help going backwards (or a better alternative) to change day of the week to actual dates.
These are my "restrictions":
My calendar control requires a date in order to display an "event" in the UI.
Employees should submit their schedule just once.
For instance:
John Doe works Mondays, Wednesdays and Fridays. 8:00 - 12:00.
That information, with my current database design, is represented in the following fashion:
ID, employee_id, day_of_week, starting_time, ending_time
1, John Doe, 1, 8:00, 12:00
2, John Doe, 3, 8:00, 12:00
3, John Doe, 5, 8:00, 12:00
I need to be able to pass a date to the calendar UI for a given month.
For instance I should be able to come up with a way to tell my calendar control:
John Doe is going to work on the 6th, 13th, 20th, and 27th taking in consideration that the only information I have is "day_of_week" = 1 (Mondays)
EDIT 2
My current but ugly solution is:
Loop through all the days of the month, and query the database day by day.
EDIT 3 - SOLUTION
Thanks to RS, I was able to solve my problem.
I kept the schedules table as it was, but I created the tables suggested by rs
After creating the tables described on the article shared by rs
The following query did the job:
SELECT CONCAT(users.firstname,\" \",users.lastname) as employee_name,
DATE_FORMAT(DATE, '%a %b %d %Y') as date, schedules.starting_time,
schedules.ending_time FROM dates_d
RIGHT JOIN schedules ON schedules.day_of_week = dates_d.day_of_week
LEFT JOIN users ON schedules.employee_id = users.ID
I JSON-Encoded an array, and the Calendar Control finally worked like a charm.

you can create date table and use key from that table and store here. The date table will allow you to query data by different date variables, ex: day, week, day of week, quarter etc - dwhworld.com/2010/08/date-dimension-sql-scripts-mysql
your schedules table will have id, emplid, date_id and you can join schedules with date table on schedules.date_id = datetble.date_id and get date, day of week in one query. You can then use this date field with your control

Why not have your day_of_week column a date type instead, that way if you want to get the day from this date you can use MySQL's DayOfWeek function. You could use this same date to pass to your calendar control (I think that's what you were getting at) in your UI.
To elaborate on your comment: Wouldn't the date that John Doe is scheduled to work be entered by the user (possibly via jQuery UI's datepicker), then when rendering your schedule at the UI level you'd use the following query to retrieve their monday schedule:
SELECT *
FROM schedules
WHERE DAYOFWEEK(schedule_date) = 1
AND employee_id = (
SELECT employee_id
FROM employees
WHERE employee_name = 'John Doe'
)
Obviously this query makes some assumptions on your employees table, and it's not particularly elegant but it serves to explain my meaning.
RE: EDIT
OK, now I see what you mean. Basically you're after a function that will give you all dates between two ranges (perhaps) that land on a specified day (let's say monday). It seems this has already been done in PHP so that might be useful? Or do have a specific technology in mind that this would need to be done in?
EDIT 3
This seems a more elegant solution: Get mondays tuesdays etc - from this you can query your DayOfWeek in the SQL and return an array of integers that you can pass as the third argument to their function.

Related

MySQL how to select all rows by specific day (mon, tue, etc) with datetime format

I have an event system setup where a user can add an event for say Monday and it can either occur once or it can be a reoccurring event. So in my application whenever the users requests to see all events for Monday I want to return any events that are on that day and also return any reoccurring events that are on Monday but could have been added in the past.
I'm not sure how the MySQL query should look. In the database I have these fields for the event.
id, title, day (DATETIME), reoccurring (TINYINT) 0/1
Thank you in advance for any guidance you can offer.
You can use the DAYNAME() function in your query.
SELECT *
FROM table
WHERE day = currentDay
OR (
DAYNAME(day) = DAYNAME(currentDay)
AND reoccuring = 1
)
For more examples of DAYNAME:
http://www.w3resource.com/mysql/date-and-time-functions/mysql-dayname-function.php

matching logs with schedule on flexi-time

I'm working on a module where the system would be able to determine where the logs of a flexi-time schedule belong...
Here's what I'm trying to do. I have a table called office_schedule with fields and values:
emp_ID time_in time_out
1 8:00:00 9:00:00
1 9:30:00 12:00:00
1 13:30:00 17:00:00
The example table Above 'office_schedule' Contains the values of schedule of a single employee in a single day. Given that I have another table called 'office_logs' with a value:
emp_ID log_in log_out
1 8:40:00 11:30:00
I searching for a query that would take the employee's logs and try to determine which value in 'office_schedule' table the logs belong to, by calculating the most value of time it has covered.
for example, if I query using the logs in 'office logs' table, it would match the second value of 'office_schedule' table, because the logs cover more span of time in the 'office_schedule' table's second value than the others.
i hope this is understandable enough.
please help...
Assuming the time cells are defined as TIME and not as VARCHAR, I would try something like that (but maybe there is a better way):
SELECT * FROM `office_logs` as log LEFT JOIN `office_schedule` AS sched ON log.`emp_ID` = sched.`emp_ID` WHERE log.`emp_ID` = 1 ORDER BY (ABS(sched.`Time_in` - log.`log_in`) + ABS(sched.`Time_out` - log.`log_out`)) ASC LIMIT 1;
It calculates the absolute difference between the log in and log out times of an employee to each of his scheduled time in and time out. The return is ordered by the smallest difference.
Maybe this helps.

Reservation system dates

I have problem thinking this trough with PHP & Mysql. I have read How to implement check availability in hotel reservation system and some more but they seem different.
I have to make a reservation system on which a converence room can be booked for 6hours minimal, so when a user make a reservation on a date e.g 24/04/2012 he then selects the start time of the rental (00:00-06:00, 06:00-12:00, 12:00-18:00,18:00-24:00). And the total number of hours(6,12,18 etc..) the user wants to rent the room.
The date is stored as a integer(timestamp).
I have two problems with this; I donĀ“t know how to receive all possible days of a month on which the room is still up for reservation and how to check if a new reservation is possible.
I know how to calculate the start date and end date on the users input but I cant find the correct mysql query or php check for availability.
It's probably really simple but somehow because the end date is always variable I just cant find the answer.
Thanks in advance guys!
EDIT Table structure: reservations
id int(11)
user_id int(11)
reservation_name varchar(255)
start_date int(11)
end_date int(11)
I believe reservations is the only one relevant
You'll find it's pretty difficult to generate a list of available days in MySQL. I recommend instead that you select an ordered list of booked days within your desired month, then loop over all days of that month in PHP skipping the day if it matches the next booked day from your MySQL query. The answer to this question will help you to build the dates over which you want to loop in PHP. In pseudocode:
$booked_days = sql(select all booked days in month order by day);
for each $day in month {
if $day != current($booked_days) {
// $day is not booked
} else advance_next($booked_days);
}
To check if a new reservation is possible, you might want to have a look at my answer to a very similar question earlier today.
This brilliant simple MySQL query must do the trick:
Checking for overlapping car reservations
This solution is only for "dates" but You can simply aggregate it with additional "hours"

Creating recurring calendar events in PHP/MySQL

I am trying to create an event calendar with recurring events (ex. weekly or monthly) but I cannot wrap my head around it. Can anyone give me some pointers? What is the best way to go about doing this? Any help is greatly appreciated. Thanks.
Create three tables with a structure like:
event table
-id
-schedule_type
-schedule_id
-title
etc.
schedule table
-id
-event_id
-datetime
schedule_recurring table
-id
-event_id
-date
-time
In your event table, the schedule_type field will be either 0 or 1, which would indicate to the application which table the scheduling information is stored in, as well as how to interpret that information.
A non-recurring event will be stored in schedule with a datetime: 2011-09-06 00:00:00, and recurring events will be stored in schedule_recurring with a date: 'every 1st Monday' and a time: 09:30,12:20 (If the event occurs twice on every first Monday of the month).
Maybe this will help get you started!
I know this is an old post but I was thinking the same thing too.
I like the persons solution about using multiple tables to do it, but in fact it can all be done from one table.
Create a table with the following data...
event_title
event_text
event_image
and_other_fields_about_event
recur_code (text)
recur_mode (integer)
start_date (date)
end_date (date)
recur_end_date (date)
recur_mode can have three states -
0 = no recurrence
1 = recurrence with end date
2 = ongoing with no end date (e.g. if you want to add something like 1st Jan as New Years Day)
recur_code would store either NULL or a code in it if the date recurs. The code that should be used there would be the PHP DateInterval code (i.e. P1Y for 1 year or P3M (3 months) or P7D (7 days), etc) - if you want to shrink the data a bit you could chop off the initial 'P' and add it back later as the initial 'P' is always going to be P, it stands for Period so "Period 3 Months" "Period 7 Days", etc.
Then when your retrieving data from the database - you retrieve all data with the following searches
( end_date >= CURDATE () ) OR ( ( recur_mode = 1 ) AND ( recur_end_date >= CURDATE () ) ) OR ( recur_mode = 2 )
(please note this isn't proper SQL - it's just a basic example of the or statement you'd need)
then once you've retrieved the data use PHP with a while loop and DateInterval to increase the start_date until you get to the next re-occurrence also making sure that if recur_mode is set to 1 the start date is not after the recur_end_date.
All done in one table - and also if you want an input form to put the code in then use a hidden field with the dateinterval value in whilst using various radio buttons to select the interval - then use jQuery onchange to update the hidden value with the new selector values.

CakePHP - event's date(s) & time(s) - how to structure

TLDR: Need to understand the best way for a user to be able to add a date(s) & time(s) for an event, and how to structure database
Explanation:
When a user adds an event, they need to be able to choose the date of the event, whether or not it will repeat daily/weekly/monthly, start and end time of the event or "all-day", if it's weekdays only or weekend...etc. Basically everything you can do w/ Google calendar when you create an event and they need to be able to edit it too (if that matters). But ALSO, they need to be able to add another date/time - for instance:
Add an event where on Monday and Wednesday of this week and three weeks from now, it goes from 8-10pm. On Tuesday and Thursday this week only, it goes from 6-9pm.
My thoughts so far:
Create a "dates" table with a HABTM relationship w/ my "events" table. When a user adds a date (with all the options of repeat..etc etc., it runs a function to process those repeats/limits...etc and adds all the dates into the dates table w/ their start/end times.
But - then how do I manage it if they want to edit that - since it just created multiple fields.
Question / Help?:
Am I even on the right track with this? I'm new to CakePHP, and it's hard for me to wrap my head around the best ways to do things... I'm not yet looking for technical help (would not turn it down though) - for now, I just need to get the idea for the best way to structure everything to be able to manage this. Maybe I need a "dates" table AND a "times" table? Maybe a "dates" table with an id that references many individual rows in a "dates_data" table?
Thank you very much ahead of time for any help / direction!
You're doing great. Let me just share my thoughts.
If I would design this, I'd have 3 models:
Event
id
user_id
description
created (datetime)
updated (datetime)
Schedule
id
event_id
description
start (datetime)
end (datetime)
duration (time, if empty(NULL) it means this is a whole day event)
repeat_time (e.g. 3:00pm means 3pm daily)
repeat_day (for weekly/monthly, e.g. Monday, Monday & Tuesday, Monday to Friday)
repeat_date (for monthly, e.g. 1 means every 1st day of month, 31 means every 31st or end of the month)
repeat_anniversary (for specific date every year, e.g. every December 25th)
Date
id
schedule_id
start (datetime)
end (datetime)
Now let's have an example of an event. Let's say we want an event that will repeat every Saturday and Sunday of May & June 2011 at 1:00pm until 3:00pm (two hours):
The events table contains the basic detail of an event. One record will be saved here.
The schedules table is separated so that you could add multiple schedules. One record will also be saved in schedule with the following fields:
duration: 02:00
start: 2011-05-01
end: 2011-06-30
repeat_time: 13:00:00
repeat_day: 01,07 (Sunday & Saturday)
Now on dates table, there will be 17 records, one for each occurrence of the schedule. The reason why I separated this is that it will be easier for me know when will the event fall. This will be useful, for example, when creating the calendar. One of the records for the dates table will look like this:
start: 2011-05-01 13:00:00
end: 2011-05-01 15:00:00
Now what if the user edits the schedule? The schedule record would be edited. All dates record would also be edited. You don't wanna delete and recreate the dates, since you might use each record for another model (e.g. user might want to tag other users as attendees for each date of the event).
I hope this helps. Goodluck on your project!

Categories