我有一个Postgres范围和一个值,并希望能够确定该值是在该范围之前,之内还是之后。
确定值是否在该范围内是微不足道的:
SELECT '[1,10]'::int4range @> 3; -- t
但是看range functions and operators,@>
运算符是我看到的唯一一个并不要求两个操作数都是范围的运算符,因此确定该值是否位于范围之前或之后是不那么直截了当。
我目前正在构建一个简单的范围来表示我的值(包含端点,两者都等于该值),然后使用<<
(严格左侧)和>>
(严格地说正确)的):
SELECT '[1,10]'::int4range << '[11,11]'::int4range; -- t
SELECT '[1,10]'::int4range >> '[-3,-3]'::int4range; -- t
这是有效的,但是必须构建这个代表单个离散值的琐碎范围,这样才能使用<<
和>>
运算符对我来说感觉有点困难。是否有一些内置函数或运算符我忽略了允许我直接使用该值进行这些查询?
我考虑并拒绝了基于使用lower(range) > value
和upper(range) < value
的方法,因为它没有考虑范围界限的包容性/排他性。
我使用的是Postgres 9.6.5,但在Postgres 10中看起来并没有发生任何变化。
答案 0 :(得分:3)
我[...]拒绝了一种基于使用较低(范围)&gt;的方法。值和上限(范围)&lt;价值,因为它没有考虑范围界限的包容性/排他性。
我不确定你的意思。 lower()
和upper()
执行帐户为包含/独占:lower('(1,10]'::int4range);
返回2,lower('[1,10]'::int4range);
返回1
在我看来,为此创建一个操作符非常简单:
创建两个函数来比较int和int4范围:
create function int_smaller_than_range(p_value int, p_check int4range)
returns boolean
as
$$
select p_value < lower(p_check);
$$
language sql;
create function int_greater_than_range(p_value int, p_check int4range)
returns boolean
as
$$
select p_value > upper(p_check);
$$
language sql;
然后创建运算符:
create operator < (
procedure = int_smaller_than_range,
leftarg = int,
rightarg = int4range,
negator = >
);
create operator > (
procedure = int_greater_than_range,
leftarg = int,
rightarg = int4range,
negator = <
);
现在可以这样使用:
select 4 > int4range(5,10); -> false
select 4 < int4range(4,10,'[]'); -> false
select 4 < int4range(4,10,'(]'); -> true
select 5 > int4range(4,10,'[]'); -> false
select 11 > int4range(4,10,'[]'); -> false
select 11 > int4range(4,10,'[)'); -> true