Check for a date/time conflict MySQL - mysql

OK... So I have a calendar, in a custom PHP application built using CodeIgniter, which pulls its entries from a MySQL database. In the table containing the entry data, there are 3 fields that govern the date (start_date), time (start_time) and duration (duration) of the entry. Now, as the end-user moves an entry to a new date and/or time, the system needs to check against these 3 fields for any schedule conflicts.
Following are some vars used in the query:
$request_entry_id // the id of the entry being moved
$request_start_date // the requested new date
$request_start_time // the requested new time
$request_duration // the duration of the entry being moved (will remain the same)
$end_time = ($request_start_time + $request_duration); // the new end time of the entry being moved
My query used to check for a schedule conflict is:
SELECT t.id
FROM TABLE t
WHERE t.start_date = '$request_start_date'
AND (j.start_time BETWEEN '$request_start_time' AND '$end_time'))
AND t.id <> $request_entry_id
The above query will check for any entry that starts on the same date and time as the request. However, I also want to check to make sure that the new request does not fall within the duration of an existing entry, in the most efficient way (there's the trick). Any suggestions? Thanks in advance!

It's easier to figure out the logic if you first think about the condition for when there is no conflict:
The new event ends before the existing one starts, or starts after the existing event ends.
For there to be a conflict we take the negative of the above:
The new event ends after the existing one starts, and starts before the existing event ends.
In SQL:
SELECT t.id
FROM TABLE t
WHERE t.start_date = '$request_start_date'
AND ('$end_time' > t.start_time AND '$request_start_time' < addtime(t.start_time, t.duration))
AND t.id <> $request_entry_id

Related

What is the best way to update another table based on a certain condition ON UPDATE?

I'm having two tables subscription and subscription_event. A subscription_event can be one of the following types:
public enum SubscriptionEventType {
CREATED,
CANCELED,
CHARGED_SUCCESSFULLY,
CHARGED_UNSUCCESSFULLY,
EXPIRED,
TRIAL_STARTED,
TRIAL_ENDED,
WENT_ACTIVE, // Subscription went active and can be charged from now on.
WENT_PAST_DUE;
public Long getValue() {
return this.ordinal() + 1L;
}
}
What I want to do is to keep the state of subscription to the most recent event. The problem: Those events do not come in correct order. E.g. it is possible to get a CHARGED_SUCCESSFULLY event before a WENT_ACTIVE event.
So there are several way how I can accomplish what I need. First of all I can check the condition in my application layer and always set that "most recent" state based on the timestamp of the event.
Long subscriptionId = lastRecordedEvent.getSubscriptionId();
if(event.getTimestamp() > lastRecordedEvent.getTimestamp()) {
// Since the current event is more recent than all other events
// we also have to update the subscription state
subscriptionRepository.updateState(subscriptionId, event.getTimestamp());
}
However, I do not want to do this in my application layer. Another solution would be to use a TRIGGER on the subscription_event table and let that on decide whether to update the relevant subscription or not. The reason why I do not go for that just yet is because I know that triggers can be easily forgotten and also be a pain to maintain. Also I know one should take every other option into account before using a TRIGGER but since I am not a SQL/MySQL expert I'm not aware of all my options here.
So what would be the most practicable way to keep subscription up-to-date in this situation?
Insert your event as usual into the table and then execute the following
UPDATE subscriptions set state=events.state
FROM subscriptions inner join events on subscriptions.id = events.subscriptionID
Where events.SubscriptionId = ? and events.Timestamp =
(select max(timestamp) from events where events.SubscriptionId = ?)
You will need to pass parameters for the two ?s to be the subscription id of the event you just inserted
EDIT
An alternative approach is rather than have a status field in the database, create a view for your subscriptions and always query the view instead.
CREATE VIEW vw_subscriptions as
Select s.id, otherfields from subscription, coalesce(e.Status, 1) as status
from subscriptions s left outer join events e on s.id=e.subscriptionId
AND e.timestamp =
(select max(timestamp) from events where subscriptionId=s.id)
If you are worried about forgetting/maintaining the SQL or triggers, document them as comments in your repository functions and maintain all changes to the database as a change script that you store with your source code. That way your changes are all in your source control.

Create a mysql event with condition

I currently have a mysql database where I keep data about rented books. When somebody rents a book, I save on the database an expiration date.
So, I want to create an mysql event to update the book status when it is not returned in time. How can I create this event?
Here's what I'm trying:
CREATE EVENT `EXPIRAR` ON SCHEDULE EVERY 1
HOUR STARTS '2016-07-16 00:00:00.000000' ENDS '2018-07-29
00:00:00.000000' ON COMPLETION NOT PRESERVE ENABLE DO DO IF
mtl_aluguel.dataLimite=CURRENT_DATE THEN
UPDATE mtl_aluguel SET mtl_aluguel.estado='Expirou'
END IF
But I'm getting Syntax errors on the IF.
mtl_aluguel is the name of my table.
Like #Drew said, my event doesnt make any sense. So I updated it:
CREATE EVENT `EXPIRAR` ON SCHEDULE EVERY 1
HOUR STARTS '2016-07-16 00:00:00.000000' ENDS '2018-07-29
00:00:00.000000' ON COMPLETION NOT PRESERVE ENABLE DO UPDATE mtl_aluguel SET mtl_aluguel.estado='Expirou' WHERE mtl_aluguel.dataLimite = CURDATE() AND mtl_aluguel.estado!= 'Expirou'

Between two datestime in mysql

I am trying to create a reservation system in php and i have a table(field_data_field_dateres) that has two fields field_dateres_value(start date) and field_dateres_value2(end date). I want to find that if conflict occurs between reservation.
Currently table has a record like this
currently i am writing query like this
SELECT * FROM `field_data_field_dateres` WHERE field_dateres_value>='2014-02-14 20:15:00' and field_dateres_value2<='2014-02-14 20:30:00';
where 2014-02-14 20:15:00,2014-02-14 20:30:00 will come from php side. But its returning empty record. thanks for any help.
Since you want to find times overlapping (conflicting), the query you want is probably instead;
SELECT * FROM `field_data_field_dateres`
WHERE field_dateres_value < '2014-02-14 20:30:00'
AND field_dateres_value2 > '2014-02-14 20:15:00';
Note that the end time is compared to your new time slot's start time, and the start time is compared to your new time slot's end time. This will return all time windows in the database that overlap with your new range.
An SQLfiddle to test with.

MySQL query for checking event conflict

Currently I making a school community site and I got a problem in a part were the administrator post a new event he/she wants check if the event start date and time has no conflict also end date and time before saving it on the database. I tried many queries still i fail to get the exact sql.
I'm using MySQL Server 5 and PHP 5.3. Can any one help me on how to query on the table i mean the right sql string.
Heres the table fields:
event_id => int,
event_type => enum('school','department'),
event_title=> text,
event_details=> longtext,
event_start=> datetime,
event_end=> datetime,
event_added_by=> int,
event_modified_on=> datetime,
Here is what i have right now:
SELECT *, time(event_start) as start_time, time(event_end) as end_time
FROM `tbl_events` WHERE ((date(event_start) between '2011-12-9' and
'2011-12-15') AND (time(event_start) between '00:00:00' and
'01:00:00')) OR ((date(event_end) between '2011-12-9' and
'2011-12-15') AND
You have four things to look for that indicate a conflict:
an existing event starts before your event starts and ends after your event ends (your event is inside the existing event)
an existing event starts before your event starts and ends after your event starts (overlap the beginning of the new event)
an existing event starts before your event ends and ends after your event ends (overlap the end of the new event)
an existing event starts after your event starts and ends before your event ends (the existing event is inside the new event)
By before and after, I mean at the same time or before/after (<= and >=).
There are two checks to do that need to be combined into one condition:
an (existing) event starts before your event ends
and
it ends after your event starts.
If the query with such a condition returns rows, there's a conflict.
I'm assuming here that the end time is the time when the event ceases to be active (or functional or valid or whatever). That is, if an event's start time equals another event's end time, there's no conflict in there. However, if that should be considered a conflict in your case, replace the before and after above with before or when and after or when respectively.
Here's how it might look in a query:
…
WHERE event_start < #new_event_end
AND event_end > #new_event_start
…
Or, if no event_start should match another event's event_end:
…
WHERE event_start <= #new_event_end
AND event_end >= #new_event_start
…
(That is, simply replace strict inequalities with non-strict ones.)
This allows also for open ends (modeled by end = null):
WHERE (event2.start < event1.end OR event1.end is null)
AND (event2.end > event1.start OR event2.end is null)
And take care whether using > or >= (respectively < or <=), this depends on your data and requirements.

Check if mySQL record added in the last x seconds

I have a mySQL database and a table where new records for a project are created. Each project created has a "project name" and an event created date (of type DATETIME).
There can be two projects created with the same name, but if they get created by the same user in quick succession, it is safe to assume it was a mistake on the user's part (clicking twice, refreshing the browser when event variables are passed, etc.).
How do I write a SQL statement to check if a record with the same name already exists, it was added in the last 10 seconds? So far I have the following, although I don't know how to check for the last 10 seconds.
select * from projects where user = 'johnsmith' AND projectname = 'test' AND active='y' AND DATE(projectcreatedon) = CURRENT_DATE AND DATEPART() < ....?
replace AND DATE(projectcreatedon) = CURRENT_DATE AND DATEPART() < ....? with:
AND projectcreatedon > (now() - INTERVAL 10 SECOND)
I would suggest not to keep such checks in MySQL because that might not be the perfect way of knowing mistakes because the user might well click the submit or refresh the page after 10 seconds. Instead, put checks in the front-end code to disable clicking the submit button twice or redirect the user to a page where no variables are passed.
But if that isn't what you would like to do, then this might be your query:
SELECT *
FROM `projects`
WHERE `user` = 'johnsmith'
AND `projectname` = 'test'
AND `active`='y'
AND TIMESTAMPDIFF(SECOND, projectcreatedon, now()) > 10;
You're trying to fix the problem in the wrong way. Why not eliminate the problem at the source? Make it impossible for the user to create these two projects successively.
If your app makes it possible for a user to submit a form multiple times via refresh, consider using a redirect after the GET/POST variables have been processed.
Furthermore, use simple client-side tricks to disable the submit button after it has been clicked once. You can accomplish this with a very small amount of jQuery