这是一个例子:
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记录。
答案 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, '[]')));
答案 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小提琴。