我正在使用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中实现这一目标?
答案 0 :(得分:0)
假设您有一个包含Preferred,date_from,date_to列的表,而您只是想计算晚上的数量。
您可以尝试此查询。
@checkout
http://sqlfiddle.com/#!9/d64344/10
您可以使用实际签到和结帐时间替换@checkin
和YourTable
次出现。
并且您可以使用实际的表名替换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