1

私のコンポーネントでは、ユーザーが予定を保存できる議題を作成しました。
アジェンダ テーブルは非常にシンプルです。タイトル、説明、開始/終了日時フィールドがあります。

ユーザーが新しいイベントを追加するとき、最初の空のスポットで彼をほのめかしたいと思います。

どうすればそれを達成できますか?
単一/束のクエリでそれは可能ですか、それとも最初の空のスポットが見つかるまでループを作成する必要がありますか?

たとえば、これは私のテーブルです:

|  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ます。この日付を取得するにはどうすればよいですか?

4

1 に答える 1

2

1 つのクエリで実行される興味深い課題:) しばらく時間がかかりましたが、解決策がありました。これらの仮定で:

  • 最低予約時間は 30 分です
  • 予定は 1 日で開始および終了します
  • 1 日は 9:00 に始まり、17:00 に終わります
  • 終了時刻と開始時刻の最小間隔は 1 分です

考慮すべき 4 つのケースがあります。

  1. 午前中はフリータイムあり
  2. 日中は自由時間あり
  3. 最初の空きスロットは、db の最後の予定の翌日です
  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()、次の有効な営業日の日付文字列に置き換えてクエリを繰り返します。

于 2012-06-14T21:23:04.967 に答える