SQL OVERLAPS运算符问题,如何摆脱它

时间:2011-03-07 10:15:26

标签: sql postgresql

我预计从'2011-01-28'到'2011-02-01'过期期间的日期从'2011-02-01'到'2011-02-01'(这是同一天),但事实并非如此!

PostgreSQL期待精确结束点的匹配不匹配...如何摆脱这个?我想让它将上述场景视为重叠。

SELECT (DATE '2011-01-28', DATE '2011-02-01') OVERLAPS
       (DATE '2011-02-01', DATE '2011-02-01');

返回false,而我希望它返回true。

5 个答案:

答案 0 :(得分:12)

你错了。来自fine manual

  

每个时间段被认为代表半开区间 start< = time<结束,除非 start end 相等,在这种情况下它代表单个时刻。这意味着,例如,只有一个共同的端点的两个时间段不会重叠。

因此,如果您想要关闭的时间间隔 start< = time< = end ,那么您可以明确地进行端点检查,如Catcall建议的那样,或者您可以添加一天上限:

SELECT (DATE '2011-01-28', DATE '2011-02-01' + 1) OVERLAPS
       (DATE '2011-02-01', DATE '2011-02-01'    )

但要注意将端点按正确顺序排列为:

  

当提供一对值时,可以先写入开头或结尾; OVERLAPS自动将该对的较早值作为开始。

答案 1 :(得分:7)

我认为最简单的方法是按原样使用重叠运算符,并添加到WHERE子句以专门处理相邻日期。

假设

  • (S1,E1)是开始和结束日期 第一个范围,
  • (S2,E2)是开始和结束日期 第二个范围,
  • S1,E1,S2或E2都不为NULL,

然后当范围重叠或相邻时,这应该返回一行。

select S1, E1, S2, E2
from [some table name]
where (S1, E1) overlaps (S2, E2)
   or (E1 = S2)   -- first range ends on the start date of the second
   or (E2 = S1)   -- second range ends on the start date of the first

答案 2 :(得分:3)

一种解决方法,即它可能会或可能没有意义 - 将日期转换为时间戳:

SELECT (TIMESTAMP '2011-01-28 00:00:00', TIMESTAMP '2011-02-01  23:59:59') OVERLAPS (TIMESTAMP '2011-02-01 00:00:00', TIMESTAMP '2011-02-01 23:59:59');

从技术上讲,只转换第一个句点的终点就足够了,至少对于你给出的例子而言。

答案 3 :(得分:0)

为什么不使用经典查询:

select (date '2013-01-01' between date '2012-12-01' and date '2013-01-01') or
       (date '2013-03-01' between date '2012-12-01' and date '2013-01-01');

在伪代码中:

select (date 'START1' between date 'START2' and date 'END2') or
       (date 'END1' between date 'START2' and date 'END2');

虽然订单会有所改变,但结果会相同:

select (date 'START2' between date 'START1' and date 'END1') or
       (date 'END2' between date 'START1' and date 'END1');

答案 4 :(得分:0)

为什么不使用PostgreSQL的数据类型daterange?使用此类型,您可以选择要绑定的包含值还是排除值。

SELECT '[2011-01-28, 2011-02-01]'::daterange &&
       '[2011-02-01, 2011-02-01]'::daterange;

&&运算符告诉您两个值是否重叠。

PostgreSQL documentation on range types