MySQL中选定的日期间隔

时间:2016-04-27 02:23:24

标签: mysql date intervals

我正在使用MySQL。我试图在一组日期间隔中获得属于每个间隔的预订的夜晚。但是有一些区间比其他区间更受欢迎,因此我将尽可能多地使用首选区间,并填充**不是优选区间**。为了说明这一点,我将在此处显示:

鉴于日期:

check in => 2016年1月16日

check out => 2016年2月8日

总晚数=> 24

      Preferred |  date_from   |  date_to   | Nights     
----------------------------------------------------
     1          |  2016-01-15  | 2016-01-17 | 2
     1          |  2016-02-03  | 2016-02-10 | 6
     1          |  2016-01-20  | 2016-01-25 | 6
     0          |  2016-01-20  | 2016-01-31 | 2 (2016-01-26 and 2016-01-31 because the other nights are covered by a preferred period)
     1          |  2016-01-27  | 2016-01-30 | 4
     0          |  2016-01-15  | 2016-01-17 | 0 (these dates are covered by a the first interval which is a preferred interval )
     0          |  2016-02-01  | 2016-02-10 | 2 (just 2016-02-01 and 2016-02-02 because 03 - 08 are covered by the second interval which is a preferred interval)
     0          |  2016-01-18  | 2016-01-19 | 2

我如何在MySQL中实现这一目标?

1 个答案:

答案 0 :(得分:0)

假设您有一个包含Preferred,date_from,date_to列的表,而您只是想计算晚上的数量。

您可以尝试此查询。

@checkout

http://sqlfiddle.com/#!9/d64344/10 您可以使用实际签到和结帐时间替换@checkinYourTable次出现。 并且您可以使用实际的表名替换n次出现

哦,是的,在sqlfiddle中,我已经包含了一个名为Numbers的列CREATE TABLE numbers AS SELECT a.n+b.n+c.n+d.n+e.n+f.n+g.n+h.n+i.n as n FROM (SELECT 0 as n UNION SELECT 1)a, (SELECT 0 as n UNION SELECT 2)b, (SELECT 0 as n UNION SELECT 4)c, (SELECT 0 as n UNION SELECT 8)d, (SELECT 0 as n UNION SELECT 16)e, (SELECT 0 as n UNION SELECT 32)f, (SELECT 0 as n UNION SELECT 64)g, (SELECT 0 as n UNION SELECT 128)h, (SELECT 0 as n UNION SELECT 256)i; ,其中包含从0向上计数的数字,以及可能的最大逗留天数。您还需要创建此表。

创建表号使用下面的

SET @checkin = '2016-01-16';
SET @checkout = '2016-02-08';

SELECT T0.preferred,T0.date_from,T0.date_to,IFNULL(NIGHTS.nights,0) as Nights
FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) T0
LEFT JOIN
    (SELECT T1.preferred,T1.date_from,T1.date_to,COUNT(*) AS Nights
       FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) AS T1
       INNER JOIN
        (SELECT (@checkin + INTERVAL n DAY) as singleday
         FROM numbers 
         WHERE (@checkin + INTERVAL n DAY) <= @checkout)DAYS1
      ON DAYS1.singleday BETWEEN T1.date_from AND T1.date_to
      WHERE T1.preferred = 1
      OR NOT EXISTS 
      (SELECT 1
       FROM (SELECT * FROM YourTable WHERE date_from <= @checkout AND date_to >= @checkin) AS T
       WHERE T.preferred = 1
         AND DAYS1.singleday BETWEEN T.date_from AND T.date_to
       )
    GROUP BY T1.preferred,T1.date_from,T1.date_to
    )NIGHTS
ON T0.preferred = NIGHTS.preferred
AND T0.date_from = NIGHTS.date_from
AND T0.date_to = NIGHTS.date_to
;
  • 解释查询

1)子查询DAYS1返回所有单个日期    从@checkin到@checkout范围

2)T1加入DAYS1 WHERE    首选是1或者不存在覆盖的首选行    DAYS1的日期

3)然后我们做一个COUNT(*)GROUP BY    首选,date_from,date_to以获取单日计数

4)然后我们调用我们的结果NIGHTS

5)然后T0与NIGHTS左撇子以获得偶数0晚的行

6)并且只返回拦截@ checkin / @ checkout范围的T0行。

更新如果您的表太大,您可以尝试使用您感兴趣的行来缩小子查询范围

onClick