Postgres查询以获取两个日期之间的结果

时间:2014-09-02 18:59:10

标签: sql postgresql date select

这是一个例子:

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');

我需要写查询,结果将是:

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";""

我写过:

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) ;

但我只看到ddd,eee和fff记录。

2 个答案:

答案 0 :(得分:2)

您可以使用PostgreSQL自己的日期(和时间)重叠检测,而不是比较运算符。实际上有两个结构:

1) SQL兼容OVERLAPS operator

  

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

这个不能很好地处理开放日期 - 但是你可以使用特殊的infinity日期。

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

据我所知,您无法使用任何索引来加速上述查询。

此外:

  

每个时间段被认为代表半开区间 start &lt; = time &lt; 结束,除非start和end相等,在这种情况下它代表单个时刻。

2)使用daterange type

范围可以是无界的,您可以明确设置如何处理范围界限(包括或不包括它们)。

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

此外,您可以通过在gist表达式上应用daterange索引来加快此查询:

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

SQLFiddle

答案 1 :(得分:1)

我猜测(聪明地)你想要任何与2014-08-15重叠的时期到现在的日期。如果是这样,这个逻辑会返回你想要的东西:

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是一个SQL小提琴。