我预计从'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。
答案 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子句以专门处理相邻日期。
假设
然后当范围重叠或相邻时,这应该返回一行。
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;
&&
运算符告诉您两个值是否重叠。