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.
Related
I am working on a booking system where users can book certain services online. I am stuck on finding and displaying available time slots within a specific day. I know the length of the needed time slot is 1 hour and the business hours.
Is there a way to show time slots that has not yet been booked on a certain day and display only the available time slots that is available to be booked in a dropdown select form?
If a customer selects a specific day and clicks "Select Day" then it needs to query the DB and return the results.
My SQL structure is as follows
|id | title | start_time | end_time | booking_date |
| 1 | Name1 | 2022-05-12 08:00:00 | 2022-05-12 09:00:00 | 2022-05-12 |
| 2 | Name2 | 2022-05-12 10:00:00 | 2022-05-12 11:00:00 | 2022-05-12 |
| 3 | Name3 | 2022-05-12 13:00:00 | 2022-05-12 14:00:00 | 2022-05-12 |
| 4 | Name4 | 2022-05-12 14:00:00 | 2022-05-12 15:00:00 | 2022-05-12 |
as per above the select form should display the timeslots that is not already taken.
09:00 - 10:00
12:00 - 13:00
15:00 - 16:00
It would be something like:
select
id, title
from
<table>
where
start_time between '2022-05-12 00:00:00' and '2022-05-12 11:59:59'
and
booking_date is null
I don't know the name of your table, so you would need to replace <table> with that. I'm also assuming that "booking_date" will have a value to indicate that time slot has been reserved, that it's a date field, and it will be null if that slot hasn't been selected. However, booking_date could have a different purpose.
This is a lazy answer
(because I think just use SQL will do it, use subSelect and other function, but I don't know how to do, sorry.)
get today occupy time:
SELECT id, TIME(start_time) AS s_time FROM tablename
WHERE start_time >= '2022-05-12 00:00:00'
AND start_time < '2022-05-13 00:00:00'
diff time in php:
$sqlResult = []; // sql result
$timeAll = [
'00:00:00',
'01:00:00',
'02:00:00',
'03:00:00',
... // TODO: we need fill it
'23:00:00',
];
foreach ($sqlResult as $item) {
if (isset($timeAll[$item['s_time']])) {
unset($timeAll[$item['s_time']]);
}
}
return $timeAll;
// TODO: javascript or other client code can use it.
ref knowledge link:
MySQL SELECT WHERE datetime matches day (and not necessarily time)
If you choose 2022-05-26, and Peter is occupying room F25 from 2022-05-16 until 2022-05-29, it means the date you select must be out of this range.
So, the query below will only return rooms that were not booked on that day.
SELECT b.id, b.room_id as available_room FROM booking as b
WHERE(
unix_timestamp('$mydate')
NOT BETWEEN unix_timestamp(b.start_date)
AND unix_timestamp(b.end_time)
)
AND unix_timestamp(b.end_time) < unix_timestamp('$mydate');
Assuming $mydate is the variable that contains the date selected by the user, the above query will return rooms that will be available in the future on that particular day.
I have two tables in a MySQL 5.7.28 database. One table with submitted XML data from a form dumped into a single column called xmlData
The second is a table with serves as a datasource for a Datatables based JS site, called Employees
When the xml data is first submitted to the xmlData table, I use the MySQL trigger below to parse and insert the data into Employees.
use test;
DELIMITER $$
DROP TRIGGER IF EXISTS test.Update_xmlData$$
CREATE TRIGGER test.Update_xmlData AFTER INSERT ON xmlData
FOR EACH ROW BEGIN
replace INTO employees (first_name, last_name, startTime, endtime, date)
select ExtractValue(xmlData, '/Data/Employee/first_name') as first_name,
ExtractValue(xmlData, '/Data/Employee/last_name') as last_name,
ExtractValue(xmlData, '/Data/Employee/StartTime') as startTime,
ExtractValue(xmlData, '/Data/Employee/EndTime') as endtime,
ExtractValue(xmlData, '/Data/Employee/date') as date
from xmlData;
END
The output of which looks like this
---------------------------------------------------------------------
first_name | last_name | startTime | endTime | Date
---------------------------------------------------------------------
Luke | Skywalker | 08:00 | 15:00 | 2019-12-05
----------------------------------------------------------------------
Santa | Clause | 08:00 | 14:00 | 2019-12-25
----------------------------------------------------------------------
This trigger works fine and inserts the data properly. The complication is that there maybe multiple start and endtimes in the submitted xmlData row. One set for each day of the week.
For the time being, I'd like to query the submitted XML and persist these values in the Employees table as separate rows. For example, if there are Monday, Tuesday and Wednesday start/end times
the inserted data would look like this:
---------------------------------------------------------------------
first_name | last_name | startTime | endTime | Date
---------------------------------------------------------------------
Luke | Skywalker | 08:00 | 15:00 | 2019-12-05
----------------------------------------------------------------------
Luke | Skywalker | 09:00 | 17:45 | 2019-12-06
----------------------------------------------------------------------
Luke | Skywalker | 06:00 | 18:00 | 2019-12-07
----------------------------------------------------------------------
Santa | Clause | 08:00 | 15:00 | 2019-12-25
----------------------------------------------------------------------
What would be the best approach for updating the trigger to insert new rows IF there are existing StartTime/EndTime for additional days of the week? Is 1 trigger even still viable at this point?
In plain English, I was thinking something along the lines of :
IF TuesdayStartTime and TuesdayEndTime EXISTS THEN insert into Employees another row retaining the same name field values, increment date by 1 day,
IF WednesdayStartTime and WednesdayEndTime EXISTS THEN insert into EMployees another row retaining the same name field values and increment date by 2 days
Submitted XML that is being queried and inserted into employees table:
XML Sample Source Schwartz 08:00 09:00 11:0018:0020191221051312
As Barmar described I can create a loop.
I also found a less elegant way that works by extracting the submitted date and using multiple triggers for each day of the week:
DATE_ADD(ExtractValue(xmlData, '/Data/Employee/date'), interval 1 Day) as date for trigger_Monday
DATE_ADD(ExtractValue(xmlData, '/Data/Employee/date'), interval 2 Day) as date for trigger_Tuesday
Creating an Index of type Unique on the Employees table prevents duplicates.
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.
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 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.)