MySQL中的连续日期可用性查询?

时间:2016-06-01 09:06:11

标签: php mysql sql

我的数据库中有一个表,其中包含以下数据:

————————————————————————————————————————————————————————————————————————
Id          startDate          availabilityStatus        Hotel_Id
————————————————————————————————————————————————————————————————————————
1          2016-07-01             available                 2
2          2016-07-02             available                 2
3          2016-07-03             unavailable               2
4          2016-07-04             available                 3
5          2016-07-05             available                 3
6          2016-07-06             available                 3
7          2016-07-07             unavailable               4
8          2016-07-08             available                 4
9          2016-07-09             available                 4
10         2016-07-10             available                 4

现在,用户希望查看 所有在2016年7月连续3天可用的酒店

我可以进行查询以获取可用性,但不确定如何获取连续日期可用性。

根据上述数据,7月份只有酒店身份3, 4有连续的可用日期,但2也有可用的日期。那么我们应该如何删除2并通过MySQL查询显示3, 4

请指教?

5 个答案:

答案 0 :(得分:4)

您可以使用以下查询:

SELECT DISTINCT t1.hotel_id
FROM mytable AS t1
JOIN mytable AS t2 
   ON t1.hotel_id = t2.hotel_id AND 
      DATEDIFF(t1.startDate, t2.startDate) = 2 AND
      t1.availabilityStatus = 'available' AND
      t2.availabilityStatus = 'available'
LEFT JOIN mytable AS t3 
   ON t1.hotel_id = t3.hotel_id AND 
      t3.startDate < t2.startDate AND t3.startDate > t1.startDate AND 
      t3.availabilityStatus = 'unavailable'  
WHERE t3.hotel_id IS NULL   

查询以这种方式编写,因此可以轻松调整以适应更长的可用期。

修改

这是使用变量的解决方案:

SELECT DISTINCT hotel_id
FROM (
  SELECT hotel_id,
         @seq := IF(@hid = hotel_id, 
                    IF(availabilityStatus = 'available', @seq + 1, 0),
                    IF(@hid := hotel_id, 
                       IF(availabilityStatus = 'available', 1, 0),
                       IF(availabilityStatus = 'available', 1, 0))) AS seq
  FROM mytable
  CROSS JOIN (SELECT @seq := 0, @hid := 0) AS vars
  ORDER BY hotel_id, startDate) AS t
WHERE t.seq >= 3  

您可以使用实际数据集对其进行测试,并告诉我们它与第一个解决方案的对比情况。

答案 1 :(得分:1)

尝试类似的东西。它适用于任何天数。将N替换为3

SELECT DISTINCT A.Hotel_Id FROM table A
WHERE 
   A.availabilityStatus = 'available' AND
   N-1 = (
      SELECT count(DISTINCT startDate) FROM table B
      WHERE B.availabilityStatus = 'available' 
        AND A.Hotel_Id = B.Hotel_Id
        AND B.startDate 
              BETWEEN DATE_ADD(A.startDate, INTERVAL 1 DAY) 
                  AND DATE_ADD(A.startDate, INTERVAL N-1 DAY) 
   )

它的工作原理如下:对于每个可用日期,计算下一天N-1的可用日期。如果他们的计数是N-1,请将hotel_id添加到结果中。

答案 2 :(得分:0)

试试这个。我没有机会测试它,因为sqlfiddle不起作用,但一般的想法是通过分别向1添加2start date天来再增加2个表格实例。

然后根据派生日期和酒店ID加入他们。

select t1.hotelid from
 (select * from Table1 where availabilityStatus='available' ) t1
inner join 
 (select a.*, DATE_ADD(startDate,INTERVAL 1 DAY) as date_plus_one 
    from Table1 where availabilityStatus='available' ) t2
on t1.start_date=t2.date_plus_one and t1.hotelid=t2.hotelid
 inner join 
(select a.*, DATE_ADD(startDate,INTERVAL 2 DAY) as date_plus_two
    from Table1 where availabilityStatus='available' ) t3
on t1.start_date=t3.date_plus_two and t1.hotelid=t3.hotelid

答案 3 :(得分:0)

此查询使用双重自我联接来查找第a,b和c天可用的同一酒店,按天分配(功能ADDDATE)。

SELECT DISTINCT a.Hotel_Id
FROM table a
INNER JOIN table b ON a.Hotel_Id=b.Hotel_Id
INNER JOIN table c ON a.Hotel_Id=c.Hotel_Id
WHERE ADDDATE(a.startDate , INTERVAL 1 DAY) = b.startDate
  AND ADDDATE(a.startDate , INTERVAL 2 DAY) = c.startDate
  AND a.availabilityStatus = 'available'
  AND b.availabilityStatus = 'available'
  AND c.availabilityStatus = 'available'

答案 4 :(得分:0)

工作正常......

SELECT a.hotel_id FROM `mytable` as a WHERE 
    (select COUNT(id) from mytable as a1 where 
        DATE(a1.startDate)=DATE_ADD(a.startDate,INTERVAL 1 DAY)  and        
        a1.hotel_id=a.hotel_id and 
        a1.availabilityStatus="Available"
    ) >0

    and

    (select COUNT(id) from mytable as a1 where 
        DATE(a1.startDate)=DATE_ADD(a.startDate,INTERVAL -1 DAY) and 
        a1.hotel_id=a.hotel_id and 
        a1.availabilityStatus="Available"
    ) >0

    and

    (select COUNT(id) from mytable as a1 where 
        DATE(a1.startDate)=DATE(a1.startDate) and
        a1.hotel_id=a.hotel_id and 
        a1.availabilityStatus="Available"
    ) >0