【问题标题】:Find first free date in agenda在议程中查找第一个空闲日期
【发布时间】:2012-06-14 19:27:13
【问题描述】:

在我的组件中,我创建了一个议程,用户可以在其中保存他们的约会。
议程表很简单:有标题、描述和开始/结束日期时间字段。

当用户添加新事件时,我希望用第一个空白点提示他。

我怎样才能做到这一点?
单个/一堆查询是否可能,或者我必须创建一个循环,直到找到第一个空点?

例如这是我的桌子:

|  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,我如何获取这个日期?

【问题讨论】:

  • 我做了一个房子。它有2间卧室、一个厨房和一个卫生间。我怎么做冰箱? - 你有什么?向我们展示您的代码,您在哪里卡住了?普通人,你问了 20 多个问题,你不是新来的!

标签: php mysql php-5.3


【解决方案1】:

在一个查询中完成有趣的挑战 :) 花了我一段时间,但我找到了解决方案。有了这些假设:

  • 最短预约时间为 30 分钟
  • 约会在一天内开始和结束
  • 一天从 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()替换为下一个有效工作日的日期字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2014-12-25
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多