How to Subtract Time between two Tables - php

I'm working on an event system and would like to know how to get the range of time available to schedule. I have the following tables
Table1 (To record the availability of creating events)
| Date | Start Time | Final Time |
| ------------- |: -------------: | ----------- |
| 2019-02-01 | 09:00:00 | 12:00:00 |
| 2019-02-01 | 13:00:00 | 17:00:00 |
and then I have Table2 to properly record the events, taking into account the availability in Table1. Table2 and Table1 have the same fields. An example of the records in Table 2 would be the following:
Table2
| Date | Start Time | Final Time |
| ------------- |: -------------: | ----------- |
| 2019-02-01 | 08:00:00 | 11:00:00 |
| 2019-02-01 | 13:00:00 | 14:30:00 |
The specific question is: What would be the SQL query to be able to determine what are the remaining time ranges, available from Table1 with respect to those that have already been taken or set out in Table2.
I'm using Laravel but I can not get the exact SQL query that works for me in this case.
I would like to get this result:
| Date | Start Time | Final Time |
| ------------- |: -------------: | ----------- |
| 2019-02-01 | 08:00:00 | 09:00:00 |
| 2019-02-01 | 11:00:00 | 12:00:00 |
| 2019-02-01 | 14:30:00 | 17:00:00 |
I hope I was clear. Thanks in advance.

Related

MySQL DELETE query works except not in PHP

I have a MySQL query to delete 'near' duplicate rows from a table, and while using test data outside of my project, the query appears to work as intended. When I use the same query with PHP in the project, I get an SQL error. I've been trying all sorts of different combinations of quotes and backticks and I can't seem to get this working.
Any idea what is going on here?
Problem being solved:
This table sometimes will have rows that are nearly identical, with the only exception being the as_of_date column and the total. Only the the most recent date is important, and any older data is no longer needed in this table once newer data comes in.
Table structure with example data:
+----+---------+------+-------------+-------+
| id | account | year | as_of_date | total |
+----+---------+------+-------------+-------+
| 1 | 123 | 2017 | 2017-02-02 | 250 |
| 2 | 123 | 2017 | 2017-11-24 | 790 |
| 3 | 123 | 2018 | 2018-01-30 | 55 |
| 4 | 456 | 2016 | 2016-04-04 | 500 |
| 5 | 456 | 2016 | 2016-10-10 | 300 |
| 6 | 456 | 2017 | 2017-03-12 | 44 |
| 7 | 789 | 2015 | 2015-12-23 | 2000 |
+----+---------+------+-------------+-------+
Expected Outcome:
The desired result is to delete all 'near-duplicate' rows in the table except for the most recent one (as_of_date). So there should only be at most 1 row for any given account and year. The table should look like this after the query is executed:
+----+---------+------+-------------+-------+
| id | account | year | as_of_date | total |
+----+---------+------+-------------+-------+
| 2 | 123 | 2017 | 2017-11-24 | 790 |
| 3 | 123 | 2018 | 2018-01-30 | 55 |
| 5 | 456 | 2016 | 2016-10-10 | 300 |
| 6 | 456 | 2017 | 2017-03-12 | 44 |
| 7 | 789 | 2015 | 2015-12-23 | 2000 |
+----+---------+------+-------------+-------+
The query:
$query = "DELETE FROM `my_table` AS t
WHERE t.as_of_date NOT IN (
SELECT MAX(as_of_date)
FROM (SELECT * FROM `my_table`) AS t2
WHERE t2.account = t.account AND t2.year = t.year
GROUP BY account, `year`
)";
Here is the SQL error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'AS t
WHERE t.as_of_date NOT IN (
S' at line 1
Don't use table aliases in DELETE FROM. That is, try DELETE FROM my_table WHERE..., omitting AS t.
By the way, the only times you really need backticks are when you have table names that are the same as reserved words or have spaces in them.
SELECT * FROM `SELECT`
or
SELECT * FROM `My Favorite Table`
Wise programmers avoid those situations.

MYSQL How to query open time slots between booked events for a set date and time?

I am attempting to create a query to list open time slots for a specific day. I have found many similar questions on here, but none of the answers seem to do the job.
The query will need to only show results between a certain time period. For instance, if I wanted to search open time slots for the a single day I would set a start date of 2017-03-17 08:00:00 (8:00am being opening time) and an end date of 2017-03-17 17:00:00 (5:00pm being the closing time for the day). It would then have to query the day and return open slots and booked appointments from my appointments table. (Note: I do not save open slots in the table or a separate table, these will need to be generated by the query).
A simplified version of my booked appointments table:
Table name: booked_appointments (before output)
+----------------------+---------------------+----------+
| start_time | end_time | duration |
+----------------------+---------------------+----------+
| 2017-03-17 10:45:00 | 2017-03-17 11:30:00 | 45 |
| 2017-03-22 09:30:00 | 2017-03-22 10:30:00 | 60 |
| 2017-03-24 08:45:00 | 2017-03-24 11:30:00 | 165 |
| 2017-03-22 11:30:00 | 2017-03-22 12:30:00 | 60 |
+----------------------+---------------------+----------+
My current MYSQL query: (I pulled this from another answer and altered for my use)
SET #timeMinimum='2017-03-17 08:00:00';
SET #timeMaximum='2017-03-17 17:00:00';
SELECT IF (d.name = 'Free', #timeMinimum, b.start_time) AS free_from,
IF (d.name = 'Free', b.start_time, #timeMinimum := b.start_time + INTERVAL b.duration MINUTE) AS free_until,
d.name AS Free
FROM (SELECT 1 AS place, 'Free' AS NAME UNION SELECT 2 AS place, 'Booked' AS NAME ) AS d
INNER JOIN booked_appointments b
HAVING free_from < free_until
UNION SELECT #timeMinimum AS free_from, #timeMaximum AS free_until, 'Free' AS Free
FROM (SELECT 1) AS d
WHERE DATE(#timeMinimum) < DATE(#timeMaximum)
ORDER BY free_from, free_until;
The query does almost everything correctly except it ignores the timeMinimum and timeMaximum I have set and it instead returns results for the entire table that ranges from 2017-03-17 through 2017-03-24. This might not be an issue once I get query working for the day but it also is ignoring the last test date that I purposefully put out of order in the table to test a real world example of data entered.
The following is output from above query:
+---------------------+---------------------+--------+
| free_from | free_until | Free |
+---------------------+---------------------+--------+
| 2017-03-17 08:00:00 | 2017-03-17 10:45:00 | Free |
| 2017-03-17 10:45:00 | 2017-03-17 11:30:00 | Booked |
| 2017-03-17 11:30:00 | 2017-03-22 09:30:00 | Free |
| 2017-03-22 09:30:00 | 2017-03-22 10:30:00 | Booked |
| 2017-03-22 10:30:00 | 2017-03-24 08:45:00 | Free |
| 2017-03-22 11:30:00 | 2017-03-22 12:30:00 | Booked |
| 2017-03-24 08:45:00 | 2017-03-24 11:30:00 | Booked |
+---------------------+---------------------+--------+
Expected output is:
+---------------------+---------------------+--------+
| free_from | free_until | Free |
+---------------------+---------------------+--------+
| 2017-03-17 08:00:00 | 2017-03-17 10:45:00 | Free |
| 2017-03-17 10:45:00 | 2017-03-17 11:30:00 | Booked |
| 2017-03-17 11:30:00 | 2017-03-17 17:00:00 | Free |
+---------------------+---------------------+--------+

select and calculate schedule dates then put them into an array

I have a table with posts I want to schedule on Facebook. No schedule dates are stored here.
I have a second table with schedule dates based on week days. All hours are the same but not all weekdays are included. Some of them are missing.
| id | mon | tue | wed | thu | fri | sat | sun |
| --- | ----- | ----- | --- | ----- | --- | ----- | ----- |
| 1 | 10:20 | 10:20 | | 10:20 | | 10:20 | 10:20 |
| 2 | 15:25 | 15:25 | | 15:25 | | 15:25 | 15:25 |
| 3 | 18:25 | 18:25 | | 18:25 | | 18:25 | 18:25 |
| 4 | 21:25 | 21:25 | | 21:25 | | 21:25 | 21:25 |
| 5 | | | | | | | |
| 6 | | | | | | | |
| 7 | | | | | | | |
Let's say we are in the first day of the week (08:00) and I want to calculate the dates for the next 100 posts (5 weeks from now). I'm thinking I ought to get an array with all these dates in UNIX time.
$array = array('1439893200','1439896200','1439833200',......'1437893200','1449893200');
I need the array because I want to output the dates when I display the posts from the database. The posts can be reordered and the dates can be changed that's why I don't store the schedule dates there. I prefer a separate table for that.
I already spent a lot of time trying to achieve this but without success. Any starting advice and help will be appreciated.
How about we start in Wednesday when there are no scheduled hours?

Select rows from specific date with left join

I'm currently working on a simple employee scheduling tool and have a problem with a SQL query. To explain my problem let use this two very abstract tables.
The first table simply consists of the employees
employees
======================
empId | name | ...
----------------------
10 | Scott |
11 | Schrute |
12 | Halpert |
13 | Howard |
In the second table you find the assigned tasks to each employee by day.
tasks
==============================================
tasId | name | task | date | ...
----------------------------------------------
10 | Scott | Support | 2014-02-17 |
11 | Scott | Bugfix | 2014-02-18 |
12 | Halpert | Bugfix | 2014-02-17 |
13 | Halpert | Develop | 2014-02-18 |
14 | Howard | Support | 2014-02-17 |
Now I want to know what the employees are working on on Feb 17th or if they have no tasks planned for that day. I use the following SQL query to do that.
SELECT e.name, t.task
FROM employees e LEFT JOIN tasks t ON e.name = t.name
WHERE date IS NULL OR date = DATE('2014-02-17')
The result delivers exactly what I need:
name | task
--------------------
Scott | Support
Schrute | NULL
Halpert | Bugfix
Howard | Support
And now to my problem. If I want to see the tasks of Feb 18th I get this result set:
name | task
--------------------
Scott | Bugfix
Schrute | NULL
Halpert | Develop
The reason to this is obvious, the date of Howard's tasks are neither NULL nor do they equal 2014-02-18.. What would be the best way to get the desired result?
I use MySQL and PHP.
(Sorry for the stupid title, I couldn't think of anything better..)
Move your filter to the join predicate:
SELECT e.name, t.task
FROM employees e
LEFT JOIN tasks t ON e.name = t.name AND t.date = DATE('2014-02-18');
Your query as it is will only return people who have no tasks at all, or have tasks on the date specified. It will omit people who have tasks, but not on the date specified. Consider the results of joining your sample data with no where clause:
empId | name | task | date | ...
----------------------------------------|
10 | Scott | Support | 2014-02-17 |
10 | Scott | Bugfix | 2014-02-18 |
11 | Schrute | NULL | NULL |
12 | Halpert | Bugfix | 2014-02-17 |
12 | Halpert | Develop | 2014-02-18 |
13 | Howard | Support | 2014-02-17 |
As you can see there is no record for Howard where Date = 2014-02-18, or where Date is null, this is why no record is returned for Howard. When you add the filter to the join predicate your results become:
empId | name | task | date | ...
----------------------------------------|
10 | Scott | Bugfix | 2014-02-18 |
11 | Schrute | NULL | NULL |
12 | Halpert | Develop | 2014-02-18 |
13 | Howard | NULL | NULL |
Which I think is the desired results.
You can use
UNIX_TIMESTAMP(`date`) = 0
Looks like you have some data which are stored as '0000-00-00' and its not null so adding the extra OR condition as above will return those data as well.

Handling Shops Open and Close time

What is the best way to store shop opening and closing time in the database and also how to calculate the time in PHP?
I have come up with this table design:
+----+---------+----------+-----------+------------+
| id | shop_id | week_day | open_hour | close_hour |
+----+---------+----------+-----------+------------+
| 1 | 3 | 1 | 15:00:00 | 23:00:00 |
| 2 | 3 | 2 | 15:00:00 | 23:00:00 |
| 3 | 3 | 3 | 18:00:00 | 02:00:00 |
| 4 | 3 | 4 | 18:00:00 | 02:00:00 |
| 5 | 3 | 5 | 18:00:00 | 03:00:00 |
+----+---------+----------+-----------+------------+
+------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| shop_id | int(11) | NO | | NULL | |
| week_day | int(11) | NO | | NULL | |
| open_hour | time | NO | | NULL | |
| close_hour | time | NO | | NULL | |
+------------+---------+------+-----+---------+----------------+
For example, on Tuesday (week_day = 2) it open at 3PM and close at 11PM (Tuesday).
On Wednesday (`week_day = 2'), it open at 6PM and close after midnight at 2AM which would be Thursday. Should after midnight time saved in same row?
Let say customer want to place an order (shop_id = 3) at 10PM on Tuesday, they should be able to do so according to the database data. However if customer want to place an order at 1AM on Thursday but the database show that week_day = 3 it close at 02:00:00
How to write in PHP to work out if the shop open or not?
Do I need to change the the table design so it would much easier to write in PHP?
Try this
http://php.net/manual/en/book.datetime.php
with this
http://php.net/manual/en/class.dateinterval.php
You can say that if close_hour is less than open_hour for a given entry that the opening hour is in the next day.
Or you could use separate week_day columns for opening and closing time.

Categories