1 つのクエリで実行される興味深い課題:) しばらく時間がかかりましたが、解決策がありました。これらの仮定で:
- 最低予約時間は 30 分です
- 予定は 1 日で開始および終了します
- 1 日は 9:00 に始まり、17:00 に終わります
- 終了時刻と開始時刻の最小間隔は 1 分です
考慮すべき 4 つのケースがあります。
- 午前中はフリータイムあり
- 日中は自由時間あり
- 最初の空きスロットは、db の最後の予定の翌日です
- 今からすべての空きスロットがあります
したがって、これらの日付から最小フォームを選択する必要があります。
そしてクエリ:
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()
、次の有効な営業日の日付文字列に置き換えてクエリを繰り返します。