1

I have a table that has a field 'start_date' and also a field 'end_date'. Items are considered active when the current date is between 'start_date' and 'end_date'. How would I find all the items that would be considered active for the next 30 days.

1
  • 1
    Can you be a little more clear on what you need, items that are active for the whole 30 days or all items that are active (regardless of duration) during the 30 day period? Commented Jul 16, 2013 at 21:28

1 Answer 1

3

Assuming start_date and end_date are DATETIME, and you want to compare the date AND time components, you could do something like this:

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

If start_date and end_date are DATE (rather than DATETIME), you probably only want to compare the DATE portion (without regard to a time component)

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

You may actually want a less than comparison (rather than less than or equal to) on the end date. You need to determine what results you want on that edge case. And the interval may need to be specified as 29 days, depending on how you define "the next 30 days".


Q: What about items that started before NOW and will run for the next 30 days?

A: I think I understand what you were asking.

I think you are wanting to retrieve any rows where the any point in time between the start_date and end_date falls anytime between now and 30 days from now. I can see that my query above does not answer that question.

For now, I'm going to consider only cases where " start_date < end_date ", and shelve cases where start_date is not less than end_date, or where either start_date or end_date or both are NULL.

We can depict the possible cases something (rather crudely) like this: The vertical bars represent NOW and NOW+30 The less than sign represents "start_date" The greater than sign represents "end_date" The dashes represent the range of DATETIME betwen start_date and 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

I think you are asking to return rows that satisfy cases 2 thru 5, which is all cases EXCEPT for case 1 and 6.

If we can write a predicate that tests for cases 1 and 6, and then negate that, it should give us what you want. Something like this:

To handle datetime with time component considered:

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

if start_date and end_date are DATE, to compare just the DATE portion, wrap the NOW() function in the DATE() function:

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

I shelved the oddball cases, of start_date > end_date, start_date = end_date, start_date IS NULL, end_date IS NULL, etc. I also omitted discussion of the edge cases (e1 thru e7), e.g. start_date = NOW(), end_date = NOW(), etc. For completeness, you probably want to check whether those cases are handled appropriately with this same predicate.


DOH!

It just dawned on me that this:

 WHERE NOT ( a < n OR b > t )

is equivalent to this (at least for not null values)

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

So this predicate should be equivalent:

 WHERE end_date >= NOW() AND start_date <= NOW() + INTERVAL 30 DAYS
Sign up to request clarification or add additional context in comments.

3 Comments

What about items that started before NOW and will run for the next 30 days?
@koala_dev: good point. I added a crude illustration of the possible cases, and added a predicate (WHERE clause) that should satisfy the requirements.
+1 Nice work @spencer7593. I think your update is exactly what the OP needed to solve his problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.