我正在用PHP / MySQL制作预订系统。
我希望能够选择一个月,选择预订长度,并在该月内查找给定长度的多少个时段(即未标记为已预订)。
我开始创建一个天数表,每天都有一个字段,表明它是否保留,以及日期。这两个表是:
CREATE TABLE `day` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` date NOT NULL,
`booking` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `booking` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` date DEFAULT NULL,
`end` date DEFAULT NULL,
PRIMARY KEY (`id`)
)
到目前为止,我已经能够计算一个月未预订的天数 - 但这并不一定能告诉我是否连续7天:
SELECT
EXTRACT(YEAR FROM date) as year,
EXTRACT( MONTH FROM date) as month,
count(day.id)
FROM
day
WHERE booking IS NULL
GROUP BY year, month
此时我正在考虑加载我给定月份的所有日子,并在PHP中迭代它们以弥补我的数字,但它似乎有点愚蠢和低效。有没有人建议我如何直接从MySQL找到这些信息?
答案 0 :(得分:2)
假设您希望2012年7月的范围至少为7天,那么:
SELECT
DATE_FORMAT(start, '%Y-%m-%d') start,
MAX(days) AS days,
DATE_FORMAT(start + INTERVAL MAX(days) - 1 DAY, '%Y-%m-%d') end
FROM (
SELECT
d2.`date` start,
(@days := IF(IFNULL(d2.booking, 0) = 0, @days + 1, 1)) AS days
FROM
(SELECT @days := 1) a,
day d1
LEFT JOIN
day d2 on d2.`date` = d1.`date` + INTERVAL 1 DAY
WHERE
IFNULL(d1.booking, 0) = 0
) d1
GROUP BY
start
HAVING
(
EXTRACT(YEAR_MONTH FROM start) = 201207 OR
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
) AND
days >= 7
ORDER BY
start
将产生此输出:
| START | DAYS | END |
----------------------------------
| 2012-06-25 | 13 | 2012-07-07 |
| 2012-06-26 | 12 | 2012-07-07 |
| 2012-06-27 | 11 | 2012-07-07 |
| 2012-06-28 | 10 | 2012-07-07 |
| 2012-06-29 | 9 | 2012-07-07 |
| 2012-06-30 | 8 | 2012-07-07 |
| 2012-07-01 | 7 | 2012-07-07 |
| 2012-07-23 | 8 | 2012-07-30 |
| 2012-07-24 | 7 | 2012-07-30 |
条款
(
EXTRACT(YEAR_MONTH FROM start) = 201207 OR
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
)
用于包括所有范围,即使范围延伸到上一个月或下个月。如果您希望范围仅在一个月内出现,请使用:
EXTRACT(YEAR_MONTH FROM start) = 201207 AND
EXTRACT(YEAR_MONTH FROM (start + INTERVAL MAX(days) - 1 DAY)) = 201207
有关互动演示,请参阅http://sqlfiddle.com/#!2/4e36a/4。
答案 1 :(得分:0)
你可以试试这个:
SELECT EXTRACT(YEAR_MONTH FROM date) AS year_month, COUNT(*) AS cnt
FROM day
LEFT JOIN booking ON booking.start <= day.date + INTERVAL 6 DAY
AND booking.end >= day.date
WHERE booking.start IS NULL
GROUP BY year_month
您的想法是,您正在寻找day
中的那些行,其中booking
的行与当天开始的7天范围不重叠。