0

假设我们有这张桌子..

CREATE TABLE `appointments` (
  `idappointments` int(11) NOT NULL AUTO_INCREMENT,
  `timeStart` time DEFAULT NULL,
  `timeEnd` time DEFAULT NULL,
  PRIMARY KEY (`idappointments`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8$$

假设

假设 timeStart 和 timeEnd 之间的范围不能再次存在......我的意思是,如果我们将表中的所有范围相交,结果将是 EMPTY ,0 ,null。约会不能与另一个约会共存......

所以我想要做的是一个时间建议,如果所需的时间被占用......在所需时间之前的建议和之后的建议......

所以我想知道,如果我可以编写一个 SQL 查询来查找最近的空范围,而不是编写代码来执行此操作......

例如.. timeStart - NEAREST_TO_TIMESTART_TIMEEND >'10 分钟',而持续时间为 10 分钟

4

1 回答 1

2

MySQL 没有递归功能,因此您只能使用 NUMBERS 表技巧 -

  1. 创建一个只包含递增数字的表 - 使用 auto_increment 很容易做到:

    DROP TABLE IF EXISTS `example`.`numbers`;
    CREATE TABLE  `example`.`numbers` (
      `id` int(10) unsigned NOT NULL auto_increment,
       PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
  2. 使用以下方法填充表:

    INSERT INTO NUMBERS
      (id)
    VALUES
      (NULL)
    

    ...根据需要获取尽可能多的值。

  3. 使用DATE_ADD构造日期列表,根据 NUMBERS.id 值增加天数。将“2010-01-01”和“2010-01-02”替换为您各自的开始和结束日期(但使用相同的格式,YYYY-MM-DD HH:MM:SS) -

    SELECT x.dt
      FROM (SELECT TIME(DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE)) AS dt
              FROM numbers n
             WHERE DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE) <= '2010-01-02' ) x
    
  4. LEFT JOIN 根据日期时间部分加入您的数据表。

这将向您显示第一个可用插槽:

       SELECT x.dt
      FROM (SELECT TIME(DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE)) AS dt
              FROM numbers n
             WHERE DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE) <= '2010-01-02' ) x
    LEFT JOIN APPOINTMENTS a ON x.dt BETWEEN a.timestart AND a.timeend
        WHERE a.idappoinment IS NULL
          AND x.dt > @your_minimum_datetime
     ORDER BY x.dt
        LIMIT 1

这将向您显示一整天的可用性:

       SELECT x.dt,
              CASE 
                WHEN a.idappoinment IS NULL THEN 'available'
                ELSE 'booked'
              END AS isbooked 
      FROM (SELECT TIME(DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE)) AS dt
              FROM numbers n
             WHERE DATE_ADD('2010-01-01', INTERVAL (n.id - 1) * 15 MINUTE) <= '2010-01-02' ) x
    LEFT JOIN APPOINTMENTS a ON x.dt BETWEEN a.timestart AND a.timeend
     ORDER BY x.dt

为什么是数字,而不是日期?

简单 - 可以根据数字生成日期,就像我提供的示例一样。这也意味着使用一个表,而不是每个数据类型一个表。

于 2010-09-16T19:39:04.467 回答