I am looking to create a booking system. On one end you have a client looking to book an appointment and on the other end you have a provider who has a schedule that a client can book against
When signing up as a provider they are allowed to pick their days of work and hours. They have html check-boxes which represent which days they can select and once they select a day the hours are are displayed (drop-downs in angular) as you can see below
html schedule form
On the MySQL side I am thinking I can have a table which has a column for each day and have a comma separated list in there for the start time, end time, lunch time and lunch length
i.e. Provider selects Monday and Tuesday to work from the hours below
Provider 'Schedule' Table
|ScheduleID|ProviderID|Monday |Tuesday |Wednesday|Thursday|Friday|Saturday|Sunday|
|----------|----------|--------|--------|---------|--------|------|--------|------|
|1 | 2 |09:00am,|10:00am,| | | | | |
| | |08:30pm,|07:00pm,| | | | | |
| | |12:00pm,|01:00pm,| | | | | |
| | |30 min |60 min | | | | | |
|----------|----------|--------|--------|---------|--------|------|--------|------|
The table would have a schedule id and a provider id which links back to the "provider" table to link the provider to his schedule
Or is this better?
|-------------|-------------|----------|-----------|----------|------------|--------------|
| schedule_id | provider_id | week_day |start_time | end_time | lunch_time | lunch_length |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 1 | 1 | Monday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 2 | 1 | Friday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
| 3 | 2 | Tuesday | 06:00 AM | 08:00 PM | 12:30 PM | 60 |
|-------------|-------------|----------|-----------|----------|------------|--------------|
if not post something that is
Before I go into how I believe you should structure your Provider 'Schedule' Table, please make sure to, in the future, remove fluff.
More on fluff here.
It may serve you better to make the following changes:
make all column headers lowercase, as this might prevent errors if you attempt to query your database another way
change scheduleId to id
Instead of having seven columns, one for every day of the week, you could simply put a weekDay column that stores the value of that weekday
Then create columns for startTime, endTime, lunchTime and lunchLength
Finally, create a scheduleId column that ties together all the different weekday rows of someone's schedule to one provider
Some considerations:
Instead of having strings "Monday" or "Sunday" in the weekDay column you could instead insert 0..6, where 0 is a Sunday and 6 is a Saturday to make it more compatible with other languages
You could always just keep scheduleId in this table and create another table with the individual schedule days and link them with a foreign key, but this might prove to cause more problems than it's worth
Keeping that lunchLength as just an integer, as that will make everything easier
The reasoning behind splitting up the data as much as possible is because if you are querying using another language you might need to go through all the extra work of splitting those Monday and Tuesday columns if you just want the startTime for instance.
Hopefully the above is either a solution or allows you to consider another approach.
Here is a Java Android Library that you can convert into JavaScript: https://bitbucket.org/warwick/schedule_utils_demo/src/master/
Running the code in a client side language will save your server the burden as scheduling code is very inefficient.
Hope this helps.
Related
I have a complex(?) SQL query I am needing to build. We have an application that captures a simple data set for multiple clients:
ClientID | AttributeName | AttributeValue | TimeReceived
----------------------------------------------------------------
002 | att1 | 123.98 | 23:02:00 02-03-20017
----------------------------------------------------------------
003 | att2 | 987.2 | 23:02:00 02-03-20017
I need to be able to return a single record per client that looks something like this
Attribute | Hour_1 | Hour_2 | Hour_x |
--------------------------------------
att1 120.67 |
--------------------------------------
att2 | 10 | 89.3 |
The hours are to be determined by a time provided to the query. If the time was 11:00 on 02-03-20017, then hour 1 would be from 10-11 on 02-03-20017, and hour 2 from 9-10 on 02-03-20017. Attributes will be allocated to these hourly buckets based on the hour/date in their time stamp (not all buckets will have data). There will be a limit on the number of hours allocated in a single query. In summary, there are possibly 200-300 attributes and hourly blocks of up to 172 hours. To be honest I am not really sure where to start to build a query like this. Any guidance appreciated.
This is what I have:
days_of_week
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | Monday |
| 2 | Tuesday |
| 3 | Wednesday |
| 4 | Thursday |
| 5 | Friday |
| 6 | Satday |
| 7 | Sunday |
+----+-------------------+
time
+----------+-------------+
| id | time |
+----------+-------------+
| Integer | hh:mm:ss |
+----+-------------------+
schedule
+---------+---------+----------+---------+
| id | user_id | time_id | day_id |
+---------+---------+----------+---------+
| Integer | Integer | Integer | Integer |
+---------+---------+----------+---------+
Where should I put the activity column, i.e. Breakfast 08:30 for example. Now 'Breakfast' has to be stored somewhere here. I cannot figure out where for the moment, but if anyone knows how to correctly Normalize this please share with me, and tell my why you are doing it that way or recommend that. Thanks a lot in advance.
What I want to achieve:
Monday: Date of that day here
08:00 Breakfast
08:30 Something else
09:00 Introduction
Tuesday: Date of that day here
08:00 Breakfast
09:00 Hackathon begins
12:30 Lunch
You get it.
To clarify:
The user can select to add a schedule, this schedule is then created and includes schedule for what will happen during those selected days, for instance, if there is an Hackathon occurring for 3 days, the user can create a schedule for those three days, with time and activity that will take place. E.g. 08:00 Breakfast, 09:00 Introduction, 09:30 Equipment Installation
Found this:
Very normalized, Method for storing/displaying repeating weekly schedule
However, it's more for repeating weekly schedule, which is not what I want to achieve.
Are you going for a repeatable week on week schedule?
If not I'd consider dropping the days of week and time tables and using a standard DATETIME field. You could pop any restrictive measures in your model validation and it could also makes detecting clashes a bit easier.
Are you looking to regularly repeat activities?
If so I'd make an activities table and reference that from the schedule.
If not, I'd probably settle for a description and time.
SIMPLE
Schedule (id, description, datetime)
REPEATABLE ACTIVITIES
Schedule (id, activity_id, datetime)
Activity (id, description)
WEEK ON WEEK SCHEDULE (w/ repeatable activities)
Schedule (id, activity_id, day_of_week_id, time)
Activity (id, description)
Day_of_week (id, title)
Always go for the simplest option that fulfills your requirements!
Normalize! Since you are already doing it:
// others omitted
activity(id, description)
day(id, time_id, activity_id)
schedule(id, day_id)
I might miss something, but open for correction.
I have a database schema like this:
sms_queue
---------------
id
status
Date Time
How do I arrange codeigniter active record to update the status only for the passed day (date time) the reference time is the time when I call the function?
Let say according to my time zone, it is on 11-01-14 (11th january 2014), and i have 5 tuple.
sms_queue
+----+--------+----------------+
| id | status | Date Time |
+====+========+================+
| 1 | unsent | 15-01-14 18:45 |
| 2 | unsent | 02-01-14 08:15 |
| 3 | unsent | 01-01-14 07:00 |
| 4 | unsent | 11-01-14 09:00 |
| 5 | unsent | 13-01-14 07:00 |
+----+--------+----------------+
what where clause on active record / sql statement should i use to select only for the second and third data above assuming today is 11-01-14
i mean the query must be like this
$this->db->where(blablabla)
->update('sms_queue',array('status'=>'sent'))
so what is the blablabla
i hope the answer is using active record not a sql statement since it says that using codeigniter active record is more safer for security issue.
Finally i could answer my own question and found the solution for my specific problem.
i use this one
$this->db->where('Date time <',date(Y-m-d))
->update('sms_queue',array('status'=>'sent'));
The query will update the status to be sent for every item who have the date time on the past day of today.
Sorry if my question is not so clear. Sorry for my bad english.
I'm looking for a bit of general advice on an approach here.
Say I have a table layout that is like:
Name | 1hr | 2hr | 3hr | 4hr
---------------------------------
Joe | 23 | 12 | 45 | 9
The hours refer to an hour ago. Or 3 hours ago. And I will be updating this data every hour. I'll be doing this with many rows. Now each time I update I will move the values to the right. So 1hr becomes 2hr etc. And 1hr is then inserted as new.
My questions is this, instead of updating each cell and then the new value is inserted what would be the most efficient way of doing this? I will be using Java and JDBC as to control these operations.
My initial though is to treat it like you would a circular array. Have an extra cell to hold a pointer to the start. This would result in 2 updates per operations vs 4.
Is this a good approach or is there something better?
The better approach would be to store another table:
Name | Time | Value
--------------------
Joe | 10:00 | 9
Joe | 11:00 | 45
Joe | 12:00 | 12
Joe | 13:00 | 23
Then you don't have to do anything to update, you just add a new row when you want to add a value.
I have this existing schema where a "schedule" table looks like this (very simplified).
CREATE TABLE schedule (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(45),
start_date date,
availability int(3),
PRIMARY KEY (id)
);
For each person it specifies a start date and percentage of work time available to spent on this project. That availability percentage implicitly continues until a newer value is specified.
For example take a project that lasts from 2012-02-27 to 2012-03-02:
id | name | start_date | availability
-------------------------------------
1 | Tom | 2012-02-27 | 100
2 | Tom | 2012-02-29 | 50
3 | Ben | 2012-03-01 | 80
So Tom starts on Feb., 27nd, full time, until Feb, 29th, from which on he'll be available only with 50% of his work time.
Ben only starts on March, 1st and only with 80% of his time.
Now the goal is to "normalize" this sparse data, so that there is a result row for each person for each day with the availability coming from the last specified day:
name | start_date | availability
--------------------------------
Tom | 2012-02-27 | 100
Tom | 2012-02-28 | 100
Tom | 2012-02-29 | 50
Tom | 2012-03-01 | 50
Tom | 2012-03-02 | 50
Ben | 2012-02-27 | 0
Ben | 2012-02-28 | 0
Ben | 2012-02-29 | 0
Ben | 2012-03-01 | 80
Ben | 2012-03-02 | 80
Think a chart showing the availability of each person over time, or calculating the "resource" values in a burndown diagram.
I can easily do this with procedural code in the app layer, but would prefer a nicer, faster solution.
To make this remotely effective, I recommend creating a calendar table. One that contains each and every date of interest. You then use that as a template on which to join your data.
Equally, things improve further if you have person table to act as the template for the name dimension of your results.
You can then use a correlated sub-query in your join, to pick which record in Schedule matches the calendar, person template you have created.
SELECT
*
FROM
calendar
CROSS JOIN
person
LEFT JOIN
schedule
ON schedule.name = person.name
AND schedule.start_date = (SELECT MAX(start_date)
FROM schedule
WHERE name = person.name
AND start_date <= calendar.date)
WHERE
calendar.date >= <yourStartDate>
AND calendar.date <= <yourEndDate>
etc
Often, however, it is more efficient to deal with it in one of two other ways...
Don't allow gaps in the data in the first place. Have a nightly batch process, or some other business logic that ensures all relevant dat apoints are populated.
Or deal with it in your client. Return each dimension in you report (data, and name) as seperate data sets to act as your templates, and then return the data as your final data set. Your client can itterate over the data and fill in the blanks as appropriate. It's more code, but can actually use less resource overall than trying to fill-the-gaps with SQL.
(If your client side code does this slowly, post another question examining that code. Provided that the data is sorted, this is acutally quite quick to do in most languages.)