【问题标题】:MySQL overlapping dates, none conflictingMySQL重叠日期,没有冲突
【发布时间】:2011-06-29 10:47:06
【问题描述】:

我在 MySQL 中看到了很多关于日期范围的主题,但我似乎仍然无法找到我正在寻找的答案,所以任何帮助都会得到很大的帮助。

我有一个包含 3 列的 MySQL 表,日期 - startTime - finishTime。日期是 MySQL 的“日期”类型字段,开始和结束时间都是“时间”类型的字段。

例如我在数据库中有一个如下条目,我们称之为会话 1;

date = 2011-06-30, startTime = 09:00:00, finishTime = 11:00:00

如果我要添加另一个会话,我需要确保它不会与现有会话冲突。因此,以下操作将失败,因为它位于会话 1 的开始时间和结束时间之间。

date = 2011-06-30, startTime = 10:00:00, finishTime = 12:00:00

因此只能在现有会话的“之后”或“之前”插入记录。

我正在使用 PHP/MySQL,并且基于查询可以运行,如果“有”匹配结果则失败,如果“没有”匹配结果则插入。

提前致谢。

【问题讨论】:

  • 当有一个与09:00 - 11:00 的会话并且新会话是11:00 - 13:00 时会发生什么。碰撞与否?
  • @Rob:那么,BETWEEN 解决方案将不起作用,因为它们会产生冲突。

标签: php mysql date range overlapping


【解决方案1】:

我正在使用 PHP/MySQL,并且基于可以运行查询,如果“有”匹配结果则失败,如果“没有”匹配结果则插入。

好吧,试试这个。这里:date: 是您要添加的条目的日期,:start-time::finish-time: 分别是它的开始和结束时间。

SELECT EXISTS (
    SELECT
        1
    FROM
        TableName
    WHERE
        `date` = :date: AND
        ( :start-time: BETWEEN startTime AND finishTime OR
          :finish-time: BETWEEN startTime AND finishTime OR
          startTime BETWEEN :start-time: AND :finish-time:
          )
) AS `Clash`

【讨论】:

  • 完美运行!非常感谢!
  • 我刚刚意识到,如果两个会话仅在它们的端点发生冲突(即一个端点是另一个会话的开始),则会报告冲突。这可能不是您想要的。发生这种情况是因为 BETWEEN 具有包容性。可以重写查询以消除使用BETWEEN 以支持严格的比较运算符<>
  • @Hammerite:没错。 x BETWEEN a AND b,应该换成a <= x AND x < b
【解决方案2】:

我遇到了日期重叠检测的问题,我的第一个想法是做一些类似 Hammerite 的解决方案,但我发现这个解决方案不完整,主要是因为两个日期范围可能发生冲突的情况太多:

我最终用来解决这个问题的查询类似于:

/* overlapping dates */
SELECT * 
FROM my_table
WHERE `date` = $date AND
  NOT (
    `start_time` < $start_time and `finish_time` < $start_time
    OR
    `start_time` > $end_time and `finish_time` > $end_time
  )

更多详情可以check my blog here

【讨论】:

    【解决方案3】:

    我会以不同的方式构建表格。我有两列,datetime 类型,命名为 session_startsession_end

    逻辑是:如果session_start 时间不是&gt;&lt; 而不是旧会话session_end,则不能插入新会话。

    【讨论】:

      【解决方案4】:

      假设 $date、$startTime 和 $finishTime 是您的 PHP 变量,它们分别存储要插入的日期、开始时间和结束时间。

      $query = 'INSERT INTO `session`
      SELECT \'' . $date . '\', \'' . $startTime . '\', \'' . $finishTime . '\'
      FROM `session`
      WHERE NOT EXISTS (SELECT *
          FROM `session`
          WHERE `date` = \'' . $date . '\'
          AND \'' . $startTime . '\' BETWEEN `startTime` and `finishTime`
      )';
      

      希望这会有所帮助。

      【讨论】:

      • 如果新会话的开始时间不在现有会话的开始和结束时间之间,但它的结束时间在?
      • 是的,我错过了添加这些条件。感谢您指出他们
      【解决方案5】:

      我会使用简单的:

      INSERT INTO session
        ( `date`, startTime, finishTime )
        SELECT
        ( $date, $startTime, $finishTime )
        WHERE NOT EXISTS
          ( SELECT
                *
            FROM
                session
            WHERE
                  `date` = $date 
              AND $startTime <  finishTime 
              AND  startTime < $finishTime 
      
          )
      

      如果您希望两个句点 09:00 - 11:0011:00 - 13:00 发生冲突,则应将 &lt; 更改为 &lt;=

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-12
        • 2015-06-26
        • 1970-01-01
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        • 2017-03-17
        • 1970-01-01
        相关资源
        最近更新 更多