Find date gaps with mysql

前端 未结 3 1983
有刺的猬
有刺的猬 2021-01-03 02:38

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:



        
3条回答
  •  耶瑟儿~
    2021-01-03 03:03

    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!

提交回复
热议问题