I have an apartment booking system and need to generate a report of number of occcupied days vs. unoccupied days within a date period on a property by property basis.
Bearing in mind within the chosen period that some bookings may start before and/or end after the start / end date respectivley.
I found this - MySQL Number of Days inside a DateRange, inside a month (Booking Table) - which is along the right lines, but I don't want it on a fixed, month by month basis but rather between two variable dates.
Ideally I'd like to do this using MySQL only but if PHP is needed then that is fine.
The only way I could think to do it would be to loop through each day individually and check if there was an occupancy on that day, but that just seems incredible inefficient.
Edit: I managed to adapt the code from the other questions as follows:
CREATE TABLE IF NOT EXISTS `view_bookings` (
`bkg_id` int(11) NOT NULL AUTO_INCREMENT,
`apt_id` int(10) NOT NULL,
`apt_name` varchar(50) NOT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
PRIMARY KEY (`bkg_id`),
UNIQUE KEY `bkg_id_UNIQUE` (`bkg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
INSERT INTO `view_bookings` (`apt_id`, `apt_name`, `start_date`, `end_date`) VALUES
(1, 'Apartment One', '2012-09-02', '2013-02-05'),
(1, 'Apartment One', '2013-02-05', '2013-07-05'),
(2, 'Apartment Two', '2012-12-25', '2013-02-28'),
(2, 'Apartment Two', '2013-03-01', '2013-04-10'),
(2, 'Apartment Two', '2013-04-16', '2013-09-19'),
(3, 'Apartment Three', '2013-01-01', '2013-02-04'),
(3, 'Apartment Three', '2013-02-06', '2013-02-12'),
(3, 'Apartment Three', '2013-02-16', '2013-02-27'),
(3, 'Apartment Three', '2013-02-27', '2013-03-14'),
(3, 'Apartment Three', '2013-03-19', '2013-06-12');
SELECT
SUM(
1 + DATEDIFF(
LEAST(end_date, '2013-03-30'),
GREATEST(start_date, '2013-02-01')
)
) AS days,
apt_name,
apt_id
FROM
view_bookings
WHERE
start_date <= '2013-03-30'
AND '2013-02-01' <= end_date
GROUP BY
apt_id
This works, however if there are overlapping bookings then it counts days twice. How can I prevent this?