What would be the optimal structure for a fixed availability schedule? - mysql

I'm setting up a calendar on which users can indicate when they are available. The calendar is split up in 3 time slots per day, for 7 days a week (monday-morning, monday-afternoon, monday-evening).
I'm a bit stuck on what the best way would be to store this in my database. I've thought about doing:
start_date
end_date
user_id
or
timeslot
user_id
or
user_id&
mon1
mon2
mon3
...
sun3
creating 21 columns doesn't seem optimal, but it does make the availability query very easy.
I would like to keep some flexibility in defining the hours for the slots. The second one appears to give me this, as I can just define the hours per day afterwards.
In the end I have to be able to look up who is available on 2019-02-01 13:00:00 - 2019-02-01 17:15:00. These dates will not correspond with the timeslots.

You can use 3 fields to store this information,
slot_date - to store date of slot like 2018-12-17, 2018-12-18, etc
slot_time - to store time slot like 13:00:00, 15:00:00, etc
user_id - to store user identifier
Let's say your sample data for 2 users with these fields will look somewhat like this,
slot_date slot_time user_id
---------------------------------
2018-12-17 14:00:00 1
2018-12-17 17:00:00 2
You can easily get the availability of the users for a given time slot. For instance, you want to fetch today's availability for afternoon slot ( considering 1 pm to 4 pm is evening slot ), which can be retrieved by following query,
SELECT slot_date, slot_time, user_id
FROM tbl_slot
WHERE slot_date = '2018-12-17'
AND slot_time BETWEEN '13:00:00' AND '15:00:00'
Similarly, you can change the slot_time clause in the query to work for morning and evening slots.
Update
Based on OP's requirement, if a user selects a day and a slot it will be applicable for every month/year. Based on it, you an eliminate the slot_date column and use day_of_week that will store integer values from 1 to 7 i.e. (Sun to Sat)
day_of_week slot_time user_id
-----------------------------------
2 14:00:00 1
2 17:00:00 2
Then, the query to get all afternoon availability will be,
SELECT day_of_week, slot_time, user_id
FROM tbl_slot
WHERE day_of_week = '2'
AND slot_time BETWEEN '13:00:00' AND '15:00:00'

Related

Selecting time-based data

What I am trying to achieve is grab data from the database, depending on the time.
For example, I may have multiple prices for an item, and I would like the new price to be effective based on the time and date. So I can schedule price changes in advance.
id link_id datetime price
-------------------------------------------
2 11 2016-11-03 00:00:00 1020
3 11 2016-11-03 01:00:00 1050
4 11 2016-11-03 03:00:00 1090
Let's say the time is 2016-11-03 00:59:00, when a user queries the db they will se the price-1020. But when they query the db a minute later at 2016-11-03 01:00:00 they should get price-1050.
Have tried this WHERE datetime < UTC_TIMESTAMP(), however this does not solve my problem. Also it only needs to select one entry, this selects multiple.
Is there a way MySQLi can do this?
If you are only looking for one item, I would expect something like this:
select p.*
from prices p
where p.item_id = $item_id and -- however you are representing items
p.datetime <= now() -- or UTC Timestamp if that is how the date/time is represented
order by p.datetime desc
limit 1;
I could speculate that "link_id" refers to "items".

MySQL store time conditions

I am currently working on a platform where I would like to offer some rentals.
I want to store all possible rental types in the database, so I do not need to take care of logic in code.
Basically I want to offer following rental-times:
1 day
7 days
5 days / need to be weekdays ( which is monday to
friday )
2 days / weekend ( needs to be saturday till sunday )
1 month / which will be from e.g. 14 of some month till 13th of following month
For the time of days I thought of storing data in minutes, this is easy to figure out.
If there is a weekday condition I thought of using the DAYOFWEEK Indexes, so I could define for 5 days, the first day of rental needs to have index 2 which is Monday, for weekend I could define that the day of rental needs to have index 6, which is Saturday.
rental_type_id | rental_time_in_minutes | rental_label | rental_start_day_indexes
1 day would be like
1 | 1440 | 1 day | 1,2,3,4,5,6,7
7 days
2 | 10080 | 7 days | 1,2,3,4,5,6,7
5 days
3 | 7200 | Weekdays | 2,3,4,5,6
etc.
Is this a way to go for, or should I store the rental time just in days?
Any help, advice, critics or cheers are helpful!
Thanks.
Depending on how you use this, storing rental time in minutes could cause issues around DST where you have 23 or 25 hours in a day.
Also storing the indices as comma-separated lists will cause you problems. I would make a mapping table. That column is not in normal form and will be tough to query.
I would honestly just make different tables for the different durations.
I would store the durations in seconds. Because it makes the whole thing easier to query and more felxible. Lets say you have those rental durations. Table durations:
d_id type duration
1 1 day 01
2 3 days 03
3 7 days 07
I would suggest that you use normal timestamps for the rentals. I would store the start and end timestamp. Lets say you have the following table.
In this example I'm using days instead of a timestamp just to make it easier to show. Let's say today is day 3. Table rentals:
customer start end
Bob 02 05
Joe 10 11
Ian 03 04
Let's say you want to want to get all the currently active rentals (Bob & Ian). You can fetch it like this:
SELECT * FROM `rentals` WHERE `start`<3 AND 3<`end`
You can find all which of rental type "1 day" (Ian) by using this query:
SELECT * FROM `rentals`,`durations` WHERE `end`-`start`=`duration` and `d_id`=1
The advantage of using timestamps is that you can very precisely set the rental start and end time. You can check how many hours and minutes the customer is too late with giving the object back. Then you can easily calculate the exact additional fees.

Get peak amount of active rows from all time

I have the following problem. I have a mysql table that has a startdate and and enddate. Each row is considered active between those dates. Some rows are no longer active, but have been active in the past. For example the following table:
id start end
1 2014-11-11 00:00:00 2015-01-31 23:59:59
2 2014-09-25 10:16:14 2015-06-01 23:59:59
3 2013-12-24 00:00:00 2014-12-01 23:59:59
4 2014-08-13 00:00:00 2016-01-31 23:59:59
5 2013-09-11 00:00:00 2014-09-10 23:59:59
My actual table has way more data than that. Now I need to know what the peak amount of concurrent active rows is without knowing when that peak actually occured. How would I do this in SQL? In the example 4 rows are active at the same time (1-4, not 5) in the time between 2014-11-11 and 2015-01-31 23:59:59. The actual peak time doesn't matter to me as much as the peak amount itself.
Thanks for your help
Find different timestamps of interrest using UNION ALL, count number of active tasks at these timestamps:
select ts, (select count(*) from tablename t2
where timestamps.ts between t2.start and t2.end) as count
from (select start as ts
from tablename
union all
select end
from tablename) as timestamps
order by count desc
limit 1
Finally order descending and pick the highest value only!
(From a non MySQL user, so some details may be wrong... Please comment if that's the case and I'll edit!)

Finding available timeslots between dates

I am creating a REST API for a booking calendar, and right now I am trying to figure out the most efficient way of writing a query that returns all timestamps between two dates with a 15 minute interval. If I supply2013-09-21 and 2013-09-22 I would like to get:
2013-09-21 00:15:00
2013-09-21 00:30:00
2013-09-21 00:45:00
2013-09-21 01:00:00
2013-09-21 01:15:00
2013-09-21 01:30:00
...
2013-09-22 23:15:00
2013-09-22 23:30:00
2013-09-22 23:45:00
I would then use this query as a subquery and apply some conditions on it to remove timeslots outside working hours (which are not constant), booked timeslots, etc.
I have seen a lot of blog posts where the author creates a "calendar table" which stores all these timestamps, but that seems like a waste to me since that data doesn't need to be stored.
Any suggestions on how I could do this or a better way to fetch/store the data?
Here is a process that generates 95 rows incrementing a date variable as it goes and then left join the table with the dated entries to the "solid" table that has generated dated rows.
select str_to_date('2010-01-01', '%Y-%m-%d') into #ad;
select * from
(select (#ad := date_add(#ad, INTERVAL 15 MINUTE)) as solid_date from wp_posts limit 95) solid
left join
wp_posts
on solid.solid_date = post_date
I've no idea how to generate an arbitrary number of rows in mysql so i'm just selecting from a table with more than 95 rows (24 hours * 4 appointments per hour less one at midnight) -- my wordpress posts table. Nothing stopping you making just such a table and having a single column with a single incrementing integer in if there are no better ways to do it (i'm an oracle guru not a mysql one). Maybe there isn't one: How do I make a row generator in MySQL?
Where you see wp_posts, substitute the name of your appointments table. Where you see the date, substitute your start date.
The query above produces a list of dates starting 15 after midnight on the chosen day (in my example 2010-01-01)
You can add a WHERE appointments.primary_key_column_here IS NULL if you want to find free slots only
Note you didn't include midnight in your spec. If you want midnight on the first day, start the date in the variable 15 minutes before and limit yourself to 96 rows. If you want midnight on the end day, just limit yourself to 96 rows

Access 2007 query to capture records that encompass 2 dates

I'm working on a query to get records based on two dates, start and end dates.
What I need to obtain are records that are span some or all of the given period, in other words the start date maybe before the parameter date but less than the end date or start after the start date and end after the end date.
I.e. Start date = 01 Oct 12 and end date 31 Oct 12. I would like to capture records where start date is before 1 Oct but spans this period whether it finishes in November or mid October. As well as records that are between 01 Oct 12 and 31 Oct 12.
In reality I need the records that exclude this period, but first need to make sure I'm getting this dataset correct.
I'm starting with this simple data set stored in MyTable, with both start_date and end_date as Date/Time data type.
id start_date end_date
1 9/29/2012 9/30/2012
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
5 11/1/2012 11/2/2012
Running the query below, and supplying 2012-10-01 and 2012-10-31 for the range_start and range_end parameters, gives me this output result set.
id start_date end_date
2 9/29/2012 10/2/2012
3 9/29/2012 11/1/2012
4 10/2/2012 11/1/2012
If this is not similar to what you wanted, please edit your question to show us a brief sample set of input data and the output you want from that sample.
Also, note the time components of my start_date and end_date values were all midnight. If your counterparts include any other times of day, you will need to revise the query to deal with them.
This is the SQL from the query I used:
PARAMETERS range_start DateTime, range_end DateTime;
SELECT m.id, m.start_date, m.end_date
FROM MyTable AS m
WHERE
m.start_date Between [range_start] And [range_end]
OR m.end_date Between [range_start] And [range_end]
OR (m.start_date<[range_start] AND m.end_date>[range_end]);