我需要从包含starts_on
字段和ends_on
字段的表格中进行选择
我需要传递开始日期和结束日期以过滤和检索这些对象。
目前正在使用以下内容:
SELECT * FROM ***
WHERE ((starts_on >= START_DATE AND starts_on <= END_DATE) OR
(ends_on >= START_DATE AND ends_on <= END_DATE) OR
(starts_on <= END_DATE AND ends_on >= END_DATE))
ORDER BY starts_on, id
它看起来有点乱,但看不到一种简单的方法来简化它。有什么想法?
我使用postgres 9.1作为dbms。
编辑:
starts_on | timestamp without time zone |
ends_on | timestamp without time zone |
例如:如果一个条目有starts_on ='2012/02/02'和ends_on'2012 / 02/05'我想要以下行为:
答案 0 :(得分:2)
如果您希望starts_on
和ends_on
之间的时间段与START_DATE
和END_DATE
的传递时间段重叠,并且“结束”始终更晚而不是“开始”,所有涉及的列都是timestamp
类型(而不是time
或date
),这个更简单的查询可以完成工作:
SELECT *
FROM tbl
WHERE starts_on <= END_DATE
AND ends_on >= START_DATE
ORDER BY starts_on, id;
稍后澄清了这个问题。
此查询的最佳索引是multi-column index,如:
CREATE INDEX tbl_range_idx ON tbl (starts_on, ends_on DESC)
几乎同样可以使用DESC / ASC
,因为可以在两个方向上搜索索引几乎同样好。
我如何计算?
在第一个条件starts_on <= END_DATE
上搜索索引,符合条件的行位于开头
从那里开始,Postgres可以根据ends_on >= START_DATE
获取所有结尾的行。合格的行是第一位的。最佳指数。
但不要只听我的话 - 用EXPLAIN ANALYZE
测试表现。运行几次以排除缓存效果。
出于同样的目的,还有OVERLAPS
运算符。简化逻辑,但不是优越的。
PostgreSQL 9.2中有新的range
types,有自己的运算符。但不适用于9.1。