关于约会的SQL查询

时间:2010-09-16 19:19:38

标签: sql mysql datetime-generation

假设我们有这张桌子..

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。一个约会cant cooexist与另一个..

所以我想做的是时间建议,如果所需的时间被占用...... 之前的提案和所需时间之后的提案......

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

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

1 个答案:

答案 0 :(得分: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到您的数据表。

  5. 这将显示第一个可用的插槽:

           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
    

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

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