MySQL overlapping dates, none conflicting - php

I've seen lots of threads about date ranges in MySQL but I still don't seem to be able to find an answer for what I'm looking for so any help will be greatly received.
I have a MySQL table with 3 columns, date - startTime - finishTime. The date is a MySQL 'date' type field and the start and finish times are both 'time' type fields.
Say for example I have an entry in the database as follows, lets call this session 1;
date = 2011-06-30, startTime = 09:00:00, finishTime = 11:00:00
If I come to add another session I need to make sure that it doesn't conflict with an existing session. So the following would fail because it falls in between session 1 start and finish times.
date = 2011-06-30, startTime = 10:00:00, finishTime = 12:00:00
So the record can only be inserted 'AFTER' or 'BEFORE' an existing session.
I'm using PHP/MySQL and am going on the basis that a query can be run and if there 'are' matching results then, fail, if there 'arent' matching results then insert.
Thanks in advance.

I'm using PHP/MySQL and am going on the basis that a query can be run and if there 'are' matching results then, fail, if there 'arent' matching results then insert.
Well, try this. Here :date: is the date of the entry you are going to add, and :start-time: and :finish-time: are its start and finish times respectively.
SELECT EXISTS (
SELECT
1
FROM
TableName
WHERE
`date` = :date: AND
( :start-time: BETWEEN startTime AND finishTime OR
:finish-time: BETWEEN startTime AND finishTime OR
startTime BETWEEN :start-time: AND :finish-time:
)
) AS `Clash`

I faced this problem of date overlapping detection, my first idea was to do something like Hammerite's solution but i found this solution incomplete mainly because there are too many possible scenarios where two date ranges can be in conflict:
The query I ended up using to solve this was something like:
/* overlapping dates */
SELECT *
FROM my_table
WHERE `date` = $date AND
NOT (
`start_time` < $start_time and `finish_time` < $start_time
OR
`start_time` > $end_time and `finish_time` > $end_time
)
For more details you can check my blog here

I would structure the table in a different way. I'd have two columns, both datetime type, named session_start and session_end.
Logic is: you cannot insert new session if it's session_start time isn't > or < than old session session_end.

Assuming $date, $startTime and $finishTime are your PHP variables that store the date, start time and finish time respectively to be inserted.
$query = 'INSERT INTO `session`
SELECT \'' . $date . '\', \'' . $startTime . '\', \'' . $finishTime . '\'
FROM `session`
WHERE NOT EXISTS (SELECT *
FROM `session`
WHERE `date` = \'' . $date . '\'
AND \'' . $startTime . '\' BETWEEN `startTime` and `finishTime`
)';
Hope this helps.

I would use the simple:
INSERT INTO session
( `date`, startTime, finishTime )
SELECT
( $date, $startTime, $finishTime )
WHERE NOT EXISTS
( SELECT
*
FROM
session
WHERE
`date` = $date
AND $startTime < finishTime
AND startTime < $finishTime
)
The < should be changed to <= if you want the two periods 09:00 - 11:00 and 11:00 - 13:00 to collide.

Related

Adding days to a Date (retrieved from MySQL database) in PHP

I am trying to do, what I assume is, an easy task of adding days to a date.
I have a date stored in a MySQL table, in a column called meta_date, with the type of DATE (A date, supported range is 1000-01-01 to 9999-12-31)
I retrieve this date from the database as follows:
$thisId = 1;
$dateQuery = mysqli_query($connection, "SELECT * FROM `sometable` WHERE `id` = '$thisId'");
$fetchDate = mysqli_fetch_assoc($dateQuery);
$theDate = $fetchDate['meta_date'];
Now I add a number of days to this date.
$newDate = date("Y-m-d", strtotime($theDate . " + 7 days"));
Next I put it back inside the database with an UPDATE query.
$editDate = mysqli_query($connection, "UPDATE `sometable` SET `meta_date` = '$newDate' WHERE `id` = '$thisId'");
However the date always returns as 0000-00-00 after the update.
Am I missing something here to do with the way the date is handled in PHP?
edit: The data I first retrieve from the database (into $theDate) is "2016-11-30".
You can use Mysql's built in function DATE_ADD()
Syntext
DATE_ADD(date,INTERVAL expr type) Where date is a valid date expression and expr is the number of interval you want to add.
For your case
UPDATE sometable
SET `meta_date` = DATE_ADD(`meta_date` , INTERVAL 7 DAY)
WHERE `id` = '$thisId';

Select between dates from table - strtotime?

I have been trying for a while, read countless stackoverflow answers and still cant crack it!
I have a table in my db with a field called dob. This field is currently just a TEXT field (but i have since tried changing it to a DATE field and still cant get it to work).
The DOB field's data is in this format (UK dates) - 22/05/2016.
Im trying to find out the number of users who's birthdays are between two dates.
For example, anyone who was born in the last two years:
$twoyearsago=date('d/m/Y', strtotime("-2 years"));
$today = date("d/m/Y");
$sql = mysql_query("SELECT * FROM users WHERE dob >= '" . $twoyearsago . "' AND date <= '" . $today . "' ORDER by id DESC");
I also tried:
$sql = mysql_query("SELECT * FROM users WHERE dob BETWEEN '" . date('d-m-Y', strtotime($twoyearsago)) . "' AND '" . date('d-m-Y', strtotime($today)) . "'";
Hopefully you can see where me logic is and hoping you will see where im going wrong - any help would be appreciated.
Jack
With STR_TO_DATE can you convert your date
NOTE: i have changed the Column type from TIMESTAMP to DATE, because in a TIMESTAMP you can store date before 1970-01-01.
SELECT STR_TO_DATE('22/05/2016','%d/%m/%Y');
sample
MariaDB [bb]> SELECT STR_TO_DATE('22/05/2016','%d/%m/%Y');
+--------------------------------------+
| STR_TO_DATE('22/05/2016','%d/%m/%Y') |
+--------------------------------------+
| 2016-05-22 |
+--------------------------------------+
1 row in set (0.00 sec)
MariaDB [bb]>
so you can change you Table
ALTER TABLE `users`
ADD COLUMN new_dob DATE;
UPDATE `users` SET new_dob = str_to_date(dob,'%d/%m/%Y');
** Verify the dates
ALTER TABLE `users`
DROP COLUMN dob;
ALTER TABLE `users`
CHANGE COLUMN `new_dob` `dob` DATE;
** CREATE an INDEX for perfomance **
ALTER TABLE `users`
ADD KEY (`dob`);
SELECT
SELECT * from `users` where dob between '2014-01-01' AND `2015-08-01';
The problem with many local date formats is that their lexical and chronological order are different (eg, 16-11-2016 comes after 11-12-2016 lexically, but before chronologically). That's why storing dates in string fields in some regional format is in most cases a bad idea: you will get sorting issues sooner or later.
Next, when specifying dates literally for MySQL, you have to respect certain formats, as explained in the documentation
Putting that into practice, the range variables should look something like this:
$today = date("Y-m-d");
$twoyearsago=date("Y-m-d", strtotime("-2 years"));
Then we use a built-in function str_to_date to convert the string column into a date that can be compared correctly:
SELECT * FROM users WHERE
STR_TO_DATE(dob, '%d/%m/%Y') between '$twoyearsago' and '$today'
This will work, but in the long run you're much better off converting that dob column into a real date format (as #BerndBuffen shows) as it's clearer, easier to internationalize and a lot better performing.
Sidenote: you are still using the long-deprecated mysql_ extension. You should really switch to either mysqli_ or PDO.
You need to build your query by using actual date values, not string. So you need format YYYY-MM-DD in query - both side of the comparison.
Try following.
$twoyearsago=date('Y-m-d', strtotime("-2 years"));
$today = date("Y-m-d");
$sql = mysql_query("SELECT * FROM users WHERE STR_TO_DATE(dob, '%d/%m/%Y') >= '" . $twoyearsago . "' AND STR_TO_DATE(dob, '%d/%m/%Y') <= '" . $today . "' ORDER by id DESC");
STR_TO_DATE(dob, '%d/%m/%Y') makes sure your d/m/Y saved dob string value to be converted to date in the query that MySQL can understand and compare with the given YYYY-MM-DD values.
Actually the proper way is creating a date field and transferring dob string values as date to this new field by using the same function unless you will always get the date values as string into the dob field.
Another method is to use DateTime and format the date before doing your query.
$begin = '10/02/2014';
$emd = '10/02/2015';
$beginDate = DateTime::createFromFormat('d/m/Y', $begin);
$emdDate = DateTime::createFromFormat('d/m/Y', $emd);
$stmt = "
SELECT
...
FROM users
WHERE birthday >= '".$beginDate->format('Y-m-d')."'
AND birthday <= '".$endDate->format('Y-m-d')."'
";

Retrieve only today records from MySQL database using PHP

In my database I stored date and time as a TIMESTAMP values. I want to retrive only today data from the database. This is code that I tried
$today = date("Y-m-d") . '00:00:00';
$last = date("Y-m-d") . '23:59:59';
$sql = "SELECT id, name, name2,some,some,submittimestamp,some FROM recs where submittimestamp Between $today AND $last";
$result = $conn->query($sql);
But I only get the 0 results message using this. There is more than 100 rows added today.
How can I solve this ? I cant change the database now. only way to solve this is change the PHP script
Do I need to convert PHP datetime to MYSQL timestamp ?
This is my sample database entry time-stamp value
2014-10-02 15:47:01
I only want to retrieve data for one day. time is not required !!
SELECT id, name, name2, submittimestamp
FROM recs WHERE submittimestamp > DATE_SUB(CURDATE(), INTERVAL 1 DAY);
Also you may try this, as DATE() ignores time part
SELECT id, name, name2, submittimestamp
FROM recs WHERE DATE(submittimestamp) = CURDATE();

Getting last 24 hours data from MySQL in PHP with custom date string

I'm adding a custom date string to the database by using;
$date = date("H:i:sa | d-m-Y");
$sql = "INSERT INTO data
(artist, title, presenter, timeplayed)
VALUES('$artist','$title','$presenter','$date')";
However I can't then quite figure out how to get $date back out but only the last 24 hours worth of entries. So between 00:00:00 yesterday and 23:59:59 today.
I've tried:
SELECT * FROM data WHERE timeplayed > DATE_SUB( NOW(), INTERVAL 24 HOUR)
And similar, however it's bringing back data older than 24 hours.
I'm storing the data in timeplayed as varchar. I wonder if that's the reason?
As per above comments you should save the data as proper mysql date format and to get the data of last 24 hours you can use the inerval of day subtracting from NOW()
SELECT * FROM data WHERE timeplayed >= NOW() - INTERVAL 1 DAY;
I think that you should rethink your approach. All of the Date functions in MySQL are geared toward the formats it expects. It would be much easier to do this in the presentation layer as:
echo date('H:i:sa | d-m-Y', strtotime($row['timeplayed']);
This will allow you to use all of the MySQL functions as expected.
Why not try:
$from_date = date("Y-m-d", strtotime("2013-12-11"))." 00:00:00";
$to_date = date("Y-m-d", strtotime("2013-12-12")." 11:59:59";
select * from data where timeplayed <= $to_date and timeplayed >= $from_date
Due to the custom date, your only savior is this query:
$sql = "SELECT * FROM data WHERE timeplayed LIKE '%".date("d-m-Y")."'";
This will yield horrid performance as your table grows...

MySQL date comparison from PHP

I would very much appreciate your help.
I have a mysql db that contains a Datetime field. In that field I have a particular date and time,
for example:
2013-10-03 22:28
I then have a PHP script that gets a particular date and time from the $_GET command, values separately: year, month, day, hour, minute.
From this GET I created a Date as follows:
$datum = $year."-".$month."-".$day." ".$hour.":".$minute.":".$seconds;
$date = date('Y-m-d H:i',strtotime($datum));
What I need to do now is somehow compare this new date I created with the last date value in the database (the most recent). The point is that after I compare this I want to check whether the last value in the db is older than 5 minutes and only then do a particular action (insert new row), and if the last date in the db is newer than 5 minutes, do nothing.
Use "select max(datetime_field) from tblname" to get the most recent value for the Datetime field.
$now = new DateTime();
$dateFromDB = new DateTime($someValueFromYourDataBase);
// subtract 5 minutes from now and compare with the stored timestamp
if ($now->sub(new DateInterval('PT5i') > $dateFromDB) {
// database timestamp is older - do something
}
you can use SQL like this:
select count(*) from `table` where `datefield` >= '$date'
$date can be calculated like
$date = date('Y-m-d H:i', strtotime($datum) - 5*60);
5*60 - it is 5 minutes
for performance reason I suggest you to add index to datefield and change select like:
select `datefield` from `table` where `datefield` >= '$date' limit 1

Categories