首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Postgres中创建包含上限的新日期范围类型?

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

Stack Overflow用户
提问于 2015-04-27 11:57:57
回答 4查看 11.9K关注 0票数 7

Postgres附带了一个名为范围类型的很好的特性,它提供了有用的范围功能(重叠、包含等)。

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

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

我想为日期实现一个范围类型,包括下限和上限,但是我碰到了Postgres文档墙:关于如何创建一个新的离散范围类型的引用是神秘的,缺乏任何示例(摘自文档:创建规范函数有点棘手,因为必须在声明范围类型之前定义它。)。

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

编辑:澄清:我正在寻找有关如何创建正确类型的信息,以便将[2014/01/01, 2014/01/31]插入到upper(daterange) = '2014/01/31'中。对于现有的daterange类型,此值将被“转换”为[2014/01/01, 2014/02/01)并提供一个upper(daterange) = '2014/02/01'

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-04-29 09:13:08

按照Postgres文档的说明,我编写了以下代码来创建我需要的类型。然而,这是行不通的(继续读)。

代码语言:javascript
复制
CREATE TYPE daterange_;

CREATE FUNCTION date_minus(date1 date, date2 date) RETURNS float AS $$
    SELECT cast(date1 - date2 as float);
$$ LANGUAGE sql immutable;

CREATE FUNCTION dr_canonical(dr daterange_) RETURNS daterange_ AS $$
BEGIN
    IF NOT lower_inc(dr) THEN
        dr := daterange_(lower(dr) + 1, upper(dr), '[]');
    END IF;
    IF NOT upper_inc(dr) THEN
        dr := daterange_(lower(dr), upper(dr) - 1, '[]');
    END IF;
    RETURN dr;
END;
$$ LANGUAGE plpgsql;

CREATE TYPE daterange_ AS RANGE (
    SUBTYPE = date,
    SUBTYPE_DIFF = date_minus,
    CANONICAL = dr_canonical    
);

据我所知,这个定义完全遵循规范。但是,它在用dr_canonical声明ERROR: SQL function cannot accept shell type daterange_函数时失败。

看起来像是 (代码也)使用C以外的任何语言声明规范函数是不可能的!因此,几乎不可能声明一个新的离散范围类型,特别是如果您使用Postgres云服务,它不允许访问运行它的机器。打得不错的波斯特格斯。

票数 0
EN

Stack Overflow用户

发布于 2015-04-27 12:21:47

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

代码语言:javascript
复制
select daterange('2014/01/01', '2014/01/31', '[]');
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

或直接投出的上限包括:

代码语言:javascript
复制
select '[2014/01/01, 2014/01/31]'::daterange;
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

编辑

不是一种新型的(错误的方法- IMHO),而是一种适当的功能:

代码语言:javascript
复制
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
票数 13
EN

Stack Overflow用户

发布于 2019-07-06 03:16:18

使用PostgresSQL 11,您可以使用Inc.函数求解表示部件,例如:

代码语言:javascript
复制
select
    WHEN upper_inc(mydaterange) THEN upper(mydaterange)
    ELSE date(upper(mydaterange)- INTERVAL '1 day')
 END 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29895077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档