I would like to extract records with having an empty bookingId and get the maximum unbooked days back (from the first free day). The expected result should be:
This should give the correct result:
select
id,
min(startDate) as startFreeDate,
count(*) - (endDate is null) numFreeDays
from (
select
pb1.id,
pb1.bookingDate startDate,
min(pb2.bookingDate) endDate
from
pricesBookings pb1 left join pricesBookings pb2
on pb1.id=pb2.id
and pb2.price>0
and pb2.bookingDate>pb1.bookingDate
where
pb1.price=0
group by
pb1.id,
pb1.bookingDate
) s
group by id, endDate
order by id, startDate
see it here.
If you need to search for all free slots of, for example, 14 days, you can add HAVING:
group by id, endDate
having count(*) - (endDate is null) >= 14
order by id, startDate
Pls try this...
select
concat_ws(',',(concat("ID=",id)),
min(startDate),
(concat((count(*) - (endDate is null))," Days Free"))) as result
from (
select
pb1.id,
pb1.bookingDate startDate,
min(pb2.bookingDate) endDate
from
pricesBookings pb1 left join pricesBookings pb2
on pb1.id=pb2.id
and pb2.price>0
and pb2.bookingDate>pb1.bookingDate
where
pb1.price=0
group by
pb1.id,
pb1.bookingDate
) s
group by id, endDate
order by id, startDateselect
concat_ws(',',(concat("ID=",id)),
min(startDate),
(concat((count(*) - (endDate is null))," Days Free"))) as result
from (
select
pb1.id,
pb1.bookingDate startDate,
min(pb2.bookingDate) endDate
from
pricesBookings pb1 left join pricesBookings pb2
on pb1.id=pb2.id
and pb2.price>0
and pb2.bookingDate>pb1.bookingDate
where
pb1.price=0
group by
pb1.id,
pb1.bookingDate
) s
group by id, endDate
order by id, startDate
Had a play with this. I might be missing something obvious but I can't see an easy way to do this with a single statement.
But I have come up with this nasty way of doing it.
SELECT z.baseid, z.bookingdate,
CASE
WHEN j.id IS NOT NULL THEN '11+ days free'
WHEN i.id IS NOT NULL THEN '10 days free'
WHEN h.id IS NOT NULL THEN '9 days free'
WHEN g.id IS NOT NULL THEN '8 days free'
WHEN f.id IS NOT NULL THEN '7 days free'
WHEN e.id IS NOT NULL THEN '6 days free'
WHEN d.id IS NOT NULL THEN '5 days free'
WHEN c.id IS NOT NULL THEN '4 days free'
WHEN b.id IS NOT NULL THEN '3 days free'
WHEN a.id IS NOT NULL THEN '2 days free'
ELSE '1 day free'
END AS DaysFree
FROM pricesbookings z
INNER JOIN pricesbookings y
ON z.baseid = y.baseid AND z.bookingid = 0 AND y.bookingid != 0 AND DATE_ADD(y.bookingdate, INTERVAL 1 DAY) = z.bookingdate
LEFT JOIN pricesbookings a ON z.baseid = a.baseid AND z.bookingid = 0 AND a.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 1 DAY) = a.bookingdate
LEFT OUTER JOIN pricesbookings b ON a.baseid = b.baseid AND b.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 2 DAY) = b.bookingdate
LEFT OUTER JOIN pricesbookings c ON b.baseid = c.baseid AND c.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 3 DAY) = c.bookingdate
LEFT OUTER JOIN pricesbookings d ON c.baseid = d.baseid AND d.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 4 DAY) = d.bookingdate
LEFT OUTER JOIN pricesbookings e ON d.baseid = e.baseid AND e.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 5 DAY) = e.bookingdate
LEFT OUTER JOIN pricesbookings f ON e.baseid = f.baseid AND f.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 6 DAY) = f.bookingdate
LEFT OUTER JOIN pricesbookings g ON f.baseid = g.baseid AND g.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 7 DAY) = g.bookingdate
LEFT OUTER JOIN pricesbookings h ON g.baseid = h.baseid AND h.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 8 DAY) = h.bookingdate
LEFT OUTER JOIN pricesbookings i ON h.baseid = i.baseid AND i.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 9 DAY) = i.bookingdate
LEFT OUTER JOIN pricesbookings j ON i.baseid = j.baseid AND j.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 10 DAY) = j.bookingdate
ORDER BY z.baseid, z.bookingdate
This only counts up to 11 or more days (easy to expand if you need to, but does need tha max number to be known in advance), and probably hideously inefficient.
Basically the table alias z is the first day, which is joined against table alias y to check that the previous day was booked. Then LEFT JOINs against a load more copies of the table each with an extra day added to the date. Then uses a CASE statement to check which is the largest one found to give you the number of days free.
Works, but your database might not appreciate it!