11

我有tstzrange类型的列(带有时区范围的时间戳),我只需要更新这个值的上限或下限(并保持包含/排除边界)

我设法改变

(-infinity,infinity)

UPDATE table
SET
    my_column = tstzrange(
        lower(my_column),
        now(),
        '()'
    )

我有

(-infinity, <current timestamp>)

但我不知道如何保持默认范围的边界..这甚至会改变[ ]( )

4

3 回答 3

9

找到了我错过的功能,可以这样做

UPDATE table
SET
    my_column = tstzrange(
        lower(my_column),
        now(),
        concat(
            CASE WHEN lower_inc(my_column) THEN '[' ELSE '(' END,
            CASE WHEN upper_inc(my_column) THEN ']' ELSE ')' END
        )
    )

最好为此创建功能。或者还有其他(更简单/更好)的解决方案吗?

于 2013-08-09T12:17:51.357 回答
3

据我所知,使用 CASE WHEN... 是获得界限的最佳方式。以下是一些简单的用户定义函数,它们返回所有本机范围类型的范围界限。

警告:这些函数的行为方式令人惊讶,因为范围类型的行为有时令人惊讶

内置范围类型int4range、int8range 和 daterange都使用包含下限但不包括上限的规范形式;那是, [)。

尽管此处指定了 '(]',但在显示时该值将转换为规范形式,因为 int8range 是离散范围类型...

(重点补充)

PostgreSQL 将 1 到 10 的封闭范围规范化为 1 到 11 的半开放范围。

select int4range('[1,10]');
[1,11)

它对左侧半开的范围做同样的事情。

select int4range('(1,10]');
[2,11)

range_bounds() 返回结果的边界,而不是输入的边界。

select range_bounds(int4range('(1,10]'));
[)

功能

create or replace function range_bounds(in range int4range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range int8range)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range numrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;


create or replace function range_bounds(in range tsrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range tstzrange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;

create or replace function range_bounds(in range daterange)
returns char(2) as 
$$
select case when lower_inc(range) then '[' else '(' end ||
       case when upper_inc(range) then ']' else ')' end;
$$
language sql
returns null on null input;
于 2013-08-10T12:40:29.857 回答
1

改进迈克斯很好的答案

当我们使用伪类型anyrange时,我们只需要一个函数:

CREATE OR REPLACE FUNCTION range_bounds(IN range anyrange)
    RETURNS CHAR(2) AS
$$
SELECT CASE WHEN lower_inc(range) THEN '[' ELSE '(' END ||
       CASE WHEN upper_inc(range) THEN ']' ELSE ')' END;
$$
LANGUAGE SQL
RETURNS NULL ON NULL INPUT;
于 2021-01-11T10:53:19.643 回答