Reputation: 882
I need to check in MySQL to see if two date intervals intersect. To explain better my issue: I have an event management module. If we have an event that was added like this:
start date :
'2013-09-09 08:00:00'
end date :
'2013-09-09 10:00:00'
and now I want to add another event that's like this:
start date :
'2013-09-09 09:00:00'
end date :
'2013-09-09 11:00:00'
OR like this :
start date :
'2013-09-09 07:00:00'
end date :
'2013-09-09 12:00:00'
I shouldn't be able to do this because an event was already added in that time interval (08-10)
For the first example (case A
), I solved the issue by doing this :
SELECT * FROM `events` as e
where
'2013-09-09 08:00:00' between e.ev_date_start and e.ev_date_end -- date start
OR
'2013-09-09 11:00:00' between e.ev_date_start and e.ev_date_end -- date end
But for the second case (case B
) I'm having trouble figuring it out...
Upvotes: 5
Views: 7515
Reputation: 3777
Having in mind that you pre-guarantee (with some UI validation) that 2013-09-09 12:00:00 is bigger than 2013-09-09 07:00:00 you can simply cross the check this way:
WHERE 1
AND '2013-09-09 07:00:00' <= e.ev_date_end
AND '2013-09-09 12:00:00' >= e.ev_date_start
This check is much simpler and faster. No need to mess up with OR statements or other complicated logic. Always have in mind that OR seriously harms the performance in SQL.
Upvotes: 1
Reputation: 786
A little example:
I want to find if these two mysql dates intersect with the dates on the database;
'2015-02-01 00:00:00', '2015-02-28 23:59:59'
The query to execute on phpMyAdmin or MySQL Workbench;
CREATE TEMPORARY TABLE `date_temp`
(
`id` int(5) NOT NULL AUTO_INCREMENT,
`date_1` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Start date',
`date_2` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Expiration date',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `date_temp` (`date_1`, `date_2`)
VALUES
('2015-01-01 00:00:00', '2015-01-30 23:59:59'),
('2015-02-02 00:00:00', '2015-02-27 23:59:59'),
('2015-03-02 00:00:00', '2015-03-31 23:59:59'),
('2015-01-15 00:00:00', '2015-03-15 23:59:59'),
('2015-01-15 00:00:00', '2015-02-15 23:59:59'),
('2015-02-15 00:00:00', '2015-03-15 23:59:59');
SELECT *
FROM `date_temp`
WHERE
NOT
(
('2015-02-01 00:00:00' > `date_2`) OR
(`date_1` > '2015-02-28 23:59:59') OR
(`date_2` < `date_1`) OR
('2015-02-28 23:59:59' < '2015-02-01 00:00:00')
);
DROP TABLE `date_temp`;
The query creates a table, inserts some data and tests if the two dates intersects with the one present on the table. Then clears the table.
Upvotes: 0
Reputation: 998
The idea is to check if they DO NOT intersect, and then negate.
NOT ('2013-09-09 08:00:00' >= e.ev_date_end OR e.ev_date_start >= '2013-09-09 11:00:00')
which is logically equivalent to
'2013-09-09 08:00:00' < e.ev_date_end AND e.ev_date_start < '2013-09-09 11:00:00'
Upvotes: 8
Reputation: 51711
Test just that the start times of already assigned time blocks or the to be assigned time block do not fall between each other.
select * from `events` as e
where '2013-09-09 08:00:00' between e.ev_date_start and e.ev_date_end
or e.ev_date_start between '2013-09-09 08:00:00'and '2013-09-09 11:00:00'
Upvotes: 5
Reputation: 52863
To cover them both you need 4 statements in your WHERE clause:
select *
from `events` as e
where '2013-09-09 07:00:00' between e.ev_date_start and e.ev_date_end
or '2013-09-09 12:00:00' between e.ev_date_start and e.ev_date_end
or e.ev_date_start between '2013-09-09 07:00:00' and '2013-09-09 12:00:00'
or e.ev_date_end between '2013-09-09 07:00:00' and '2013-09-09 12:00:00'
It might look simpler like this:
select *
from `events` as e
where @start between e.ev_date_start and e.ev_date_end
or @end between e.ev_date_start and e.ev_date_end
or e.ev_date_start between @start and @end
or e.ev_date_end between @start and @end
Upvotes: 5