0

This is example:

create table test (
id int,
name varchar(6),
start_date date,
end_date date
);


insert into test (id,name, start_date, end_date) values (1,'aaa', '2014-07-01', '2014-07-30');
insert into test (id,name, start_date, end_date) values (2,'bbb', '2014-07-01', '2014-08-30');
insert into test (id,name, start_date, end_date) values (3,'ccc', '2014-08-01', '2014-08-30');
insert into test (id,name, start_date, end_date) values (4,'ddd', '2014-08-16', '2014-08-30');
insert into test (id,name, start_date) values (5,'eee', '2014-07-01');
insert into test (id,name, start_date) values (6,'fff', '2014-08-16');

I need write query where result will be:

2;"bbb";"2014-07-01";"2014-08-30"
3;"ccc";"2014-08-01";"2014-08-30"
4;"ddd";"2014-08-16";"2014-08-30"
5;"eee";"2014-07-01";""
6;"fff";"2014-08-16";""

I've written this:

select * from test
where (start_date >= '2014-08-15' and (end_date <= current_Date or end_date is null)) or 
(start_date <= '2014-08-15' and end_date is null) ;

But I see only ddd,eee and fff records.

1
  • What did you expect ? Your WHERE clause is working as designed. Commented Sep 2, 2014 at 19:01

2 Answers 2

2

Instead of the compare operators, you can actually use PostgreSQL's own detection of date (& time) overlaping. There are actually 2 constructs:

1) The SQL compatible OVERLAPS operator:

(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)

This one does not handle well an open-ended date-period, but you can use the the special infinity date for that.

select *
from   test
where  (date '2014-08-15', current_date) overlaps
       (start_date, coalesce(end_date, date 'infinity'));

As far as I know, you can't use any index to speed up the query above.

Also:

Each time period is considered to represent the half-open interval start <= time < end, unless start and end are equal in which case it represents that single time instant.

2) Using the daterange type:

Ranges can be unbounded, and you can explicitly set how to handle range bounds (to include them or not).

select *
from   test
where  daterange(start_date, end_date, '[]') &&
       daterange(date '2014-08-15', current_date, '[]');

Also, you can speed up this query, by applying a gist index on the daterange expression:

create index on test using gist ((daterange(start_date, end_date, '[]')));

SQLFiddle

Sign up to request clarification or add additional context in comments.

Comments

1

I am guessing (intelligently) that you want any period that overlaps with 2014-08-15 to the present date. If so, this logic returns what you want:

select *
from test
where (start_date >= '2014-08-15' and (end_date <= current_Date or end_date is null)) or 
      (start_date <= '2014-08-15' and (end_date > '2014-08-15' or end_date is null));

Here is a SQL Fiddle.

1 Comment

Indeed ^^ You are my hero! Thanks a lot!

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.