1

我有一个表,其中包含一个字段“start_date”和一个字段“end_date”。当当前日期在“start_date”和“end_date”之间时,项目被认为是活动的。我如何找到在接下来的 30 天内被视为处于活动状态的所有项目。

4

1 回答 1

3

假设start_dateend_date是 DATETIME,并且您想比较日期和时间组件,您可以执行以下操作:

SELECT a.*
  FROM atable a
 WHERE a.start_date >= NOW()
   AND a.end_date   <= NOW() + INTERVAL 30 DAYS

如果 start_date 和 end_date 是 DATE(而不是 DATETIME),您可能只想比较 DATE 部分(不考虑时间组件)

SELECT a.*
  FROM atable a
 WHERE a.start_date >= DATE(NOW())
   AND a.end_date   <= DATE(NOW()) + INTERVAL 30 DAYS

您实际上可能希望在结束日期进行小于比较(而不是小于或等于)。您需要确定在该边缘情况下想要什么结果。并且可能需要将间隔指定为 29 天,具体取决于您如何定义“接下来的 30 天”。


问:在 NOW 之前开始并且将在接下来的 30 天内运行的项目呢?

A:我想我明白你在问什么。

我认为您想要检索 start_date 和 end_date 之间的任何时间点从现在到 30 天之间的任何时间点的任何行。我可以看到我上面的查询没有回答这个问题。

现在,我将只考虑“ start_date < end_date ”的情况,以及 start_date 不小于 end_date 或 start_date 或 end_date 或两者都为 NULL 的情况。

我们可以像这样(相当粗略地)描述可能的情况: 竖线表示 NOW 和 NOW+30 小于号表示“start_date” 大于号表示“end_date” 破折号表示 DATETIME 在 start_date 和 end_date 之间的范围

      NOW     NOW+30
<--->  |       |              case 1: end_date < NOW()
   <---|---->  |              case 2: NOW() between start_date and end_date
    <--|-------|---->         case 3: NOW() > start_date and NOW+30 < end_date
       | <---> |              case 4: both start_date and end_date between NOW() and NOW()+30
       |    <--|--->          case 5: start_date between NOW() and NOW()+30 and end_date > NOW+30 
       |       |  <--->       case 6: start_date > NOW()+30


   <--->       |              case e1: end_date = NOW()
    <--|------->              case e2: start_date > NOW() AND end_date = NOW()+30
       <--->   |              case e3: start_date = NOW() and end_date < NOW()+30
       <------->              case e4: start_date = NOW() and end_date = NOW()+30
       <-------|-->           case e5: start_date = NOW() and end_date > NOW()+30
       |   <--->              case e6: start_date > NOW() AND end_date = NOW()+30
       |       <--->          case e7: start_date = NOW()+30

我认为您要求返回满足案例 2 到 5 的行,除案例 1 和案例 6 外,所有案例都是如此。

如果我们可以编写一个谓词来测试案例 1 和 6,然后否定它,它应该给我们你想要的。像这样的东西:

要处理考虑时间分量的日期时间:

  WHERE NOT ( end_date < NOW() OR start_date > NOW() + INTERVAL 30 DAYS )

如果 start_date 和 end_date 是 DATE,要仅比较 DATE 部分,请将 NOW() 函数包装在 DATE() 函数中:

  WHERE NOT ( end_date < DATE(NOW()) OR start_date > DATE(NOW()) + INTERVAL 30 DAYS )

我搁置了 start_date > end_date、start_date = end_date、start_date IS NULL、end_date IS NULL 等古怪案例。我还省略了对边缘案例(e1 到 e7)的讨论,例如 start_date = NOW()、end_date = NOW( ) 等。为了完整起见,您可能需要检查这些情况是否使用相同的谓词进行了适当的处理。


哦!

我突然意识到:

 WHERE NOT ( a < n OR b > t )

相当于这个(至少对于非空值)

 WHERE ( a >= n AND b <= t )

所以这个谓词应该是等价的:

 WHERE end_date >= NOW() AND start_date <= NOW() + INTERVAL 30 DAYS
于 2013-07-16T20:42:38.997 回答