在我的组件中,我创建了一个议程,用户可以在其中保存约会 议程表非常简单:有标题,描述和开始/结束日期时间字段。
当用户添加新活动时,我希望用第一个空白点暗示他。
我怎样才能做到这一点?
这可能是单个/一堆查询,或者我必须创建一个循环,直到找到第一个空白点?
例如,这是我的表:
| ID | Start date | End date |
| 1 | 2012-06-14 09:00:00 | 2012-06-14 09:32:00 |
| 2 | 2012-06-14 15:00:00 | 2012-06-14 15:45:00 |
| 3 | 2012-06-14 18:20:00 | 2012-06-14 18:55:00 |
第一个免费日期时间应为2012-06-14 09:33:00
,我该如何获取此日期?
答案 0 :(得分:2)
有趣的挑战要在一个查询中完成:)我花了一段时间,但我带来了解决方案。有了这些假设:
有4个案例需要考虑:
所以你必须选择这些日期的最低格式。
查询:
SELECT
MIN(next_start_date) AS next_start_date
FROM
(
(
SELECT
DATE_FORMAT(t1.start_date,'%Y-%m-%d 09:00:00') AS next_start_date
FROM
agenda t1
WHERE
t1.start_date > NOW()
AND
TIME(t1.start_date) > '09:30:00'
AND
NOT EXISTS(
SELECT 1 FROM agenda t2 WHERE DATE(t2.start_date) = DATE(t1.start_date) AND TIME(t2.start_date) <= '09:30:00'
)
LIMIT 1
)
UNION
(
SELECT
t3.end_date + INTERVAL 1 MINUTE AS next_start_date
FROM
agenda t3
WHERE
t3.start_date > NOW()
AND
TIME(t3.start_date) >= '09:00:00'
AND
TIME(t3.end_date) < '16:30:00'
AND NOT EXISTS
(SELECT 1 FROM agenda t4 WHERE TIMESTAMPDIFF(MINUTE,t3.end_date,t4.start_date) BETWEEN 0 AND 30 )
ORDER BY
t3.start_date ASC
LIMIT 1
)
UNION
(
SELECT CONCAT(CAST(DATE((SELECT MAX(t5.start_date) + INTERVAL 1 DAY FROM agenda t5 WHERE t5.start_date > NOW())) AS CHAR), ' 09:00:00') AS next_start_date
)
UNION
(
SELECT
IF(
TIME(NOW()) < '09:00:00',
DATE_FORMAT(NOW(),'%Y-%m-%d 09:00:00'),
IF(
TIME(NOW()) < '16:30',
NOW(),
DATE_FORMAT(NOW() + INTERVAL 1 DAY,'%Y-%m-%d 09:00:00' )
)
) AS next_start_date
FROM
(SELECT 1) t6
WHERE NOT EXISTS(
SELECT 1 FROM agenda t7 WHERE t7.start_date > NOW()
)
LIMIT 1
)
) t
当然它并不完美 - 当第二天出现下一个免费插槽时,有可能是星期六或其他一天下班。考虑到这一点,最好的方法是检查返回是否为有效工作日,如果不是,则重复查询,NOW()
替换为下一个有效工作日的日期字符串。