如何在Postgres中创建包含上限的新日期范围类型?

时间:2015-04-27 11:57:58

标签: postgresql date-range

Postgres附带了一个名为Range Types的好功能,它提供了有用的范围功能(重叠,包含等)。

我希望使用daterange类型,但我认为该类型是通过一个尴尬的选择实现的:日期范围的上限是排除。这意味着,如果我将我的值定义为2014/01/01 - 2014/01/31,则会显示为[2014/01/01, 2014/01/31),并且该范围内的排除的1月31日!

我认为这是错误的默认选择。我不能想到现实生活中的任何应用或参考,假设日期范围的结束日期被排除在外。至少不符合我的经验。

我想为包含下限和上限的日期实现范围类型,但是我正在使用Postgres文档墙:关于如何创建新的离散范围类型的参考资料是含糊不清的,缺少任何示例(取自文档:Creating a canonical function is a bit tricky, since it must be defined before the range type can be declared)。

有人可以提供一些帮助吗?甚至直接实施本身;它应该是5-10行代码,但将这5-10行放在一起是一项严肃的研究工作。

编辑:澄清:我正在寻找有关如何创建正确类型的信息,以便插入[2014/01/01, 2014/01/31]导致upper(daterange) = '2014/01/31'。使用现有的日期范围类型,此值将“转换”为[2014/01/01, 2014/02/01)并提供upper(daterange) = '2014/02/01'

3 个答案:

答案 0 :(得分:5)

注意第三个构造函数参数:

select daterange('2014/01/01', '2014/01/31', '[]');
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

或包含上限的直接演员:

select '[2014/01/01, 2014/01/31]'::daterange;
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

修改

不是新类型(错误的方法恕我直言),而是一个正确的功能:

create function inclusive_upper_daterange(dtr daterange)
returns date as $$

    select upper(dtr) - 1;

$$ language sql immutable;

select inclusive_upper_daterange('[2014/01/01, 2014/01/31]'::daterange);
 inclusive_upper_daterange 
---------------------------
 2014-01-31

答案 1 :(得分:0)

使用PostgresSQL 11,您可以使用upper_inc函数来解决表示部分,例如:

select
    WHEN upper_inc(mydaterange) THEN upper(mydaterange)
    ELSE date(upper(mydaterange)- INTERVAL '1 day')
 END 

答案 2 :(得分:-1)

CREATE or replace FUNCTION to_timestamptz(arg1 timestamptz, arg2 timestamptz) RETURNS float8 AS
'select extract(epoch from (arg2 - arg1));' LANGUAGE sql STRICT
                                                         IMMUTABLE;
;
create type tsrangetz AS RANGE
(
  subtype = timestamptz,
  subtype_diff =
  to_timestamptz
)
;
select tsrangetz(current_date, current_date + 1)
--["2020-10-05 00:00:00+07","2020-10-06 00:00:00+07")
;