将int范围排序为PostgreSQL日期范围

时间:2018-04-11 22:00:30

标签: postgresql sorting date integer range

因为PostgreSQL中的BC日期仅在公元前4713年停止,并且我不想一般限制BC日期,所以我决定使用int作为日期。

执行select * from test order by daterange;后,这是我的表格:

id  daterange
26  [-6000501,-6000301)
27  [-6000401,-6000201)
22  [-4001202,-4000102)
23  [-4000702,-4000302)
19  [-3010102,-3000102)
21  [-3001202,-3000102)
14  [-3001011,-2000101)
15  [-1000506,6000701)
20  [3000102,3001201)
16  [12500709,13650230)
17  [14580102,16590507)

有一些int范围代表按时间顺序排列的时代。负数是BC日期。模式为YYYYMMDD

问题是id 27 [-6000401,-6000201)应该是第一个而id 26 [-6000501,-6000301)秒,因为BC日期被翻转:上限按时间顺序排在第一位。此外,一年内的几个月没有下降,他们上升。但是PostgreSQL试图保存负数,而不是关于时间顺序内容的线索。所以他们应该这样订购:

  1. -6000201,然后是-6000401(2月6日,然后是4月)
  2. -6000301,然后是-6000501(3月6日,3月,然后是5月)
  3. 因此:

    id 27 [-6000401,-6000201)  -- first
    id 26 [-6000501,-6000301)  -- second
    

    要清楚,我不想切换范围内的界限 - 这是不可能的。我想根据最大界限翻转排序顺序,就像上面一样。我不知道如何对这种范围进行排序。它应该根据它们的上限对它们进行排序,我猜是DESC?我试过像

    这样的东西
    SELECT * FROM test  
    ORDER BY daterange ASC 
    , CASE WHEN (upper(daterange)<0) AND (lower(daterange)<0) THEN daterange END DESC;
    

    但是我得到了相同的订单。我使用PostgreSQL 10.

    也许我还没有其他的解决方法或方法。或者也许是无限制BC日期的插件 - 即使我没有找到任何。

2 个答案:

答案 0 :(得分:1)

在坚持使用您的广告素材日期格式时,这应该达到正确的升序排序顺序:

SELECT *
     , upper(daterange), upper(daterange)/10000, upper(daterange)%10000
     , lower(daterange), lower(daterange)/10000, lower(daterange)%10000
FROM   test  
ORDER  BY CASE WHEN upper(daterange) >= 0 THEN daterange END NULLS FIRST 
                                       -- BC before AD, fully sort AD
        , upper(daterange)/10000       -- BC by start year
        , upper(daterange)%10000 DESC  -- BC by start date
        , lower(daterange)/10000       -- BC by end year
        , lower(daterange)%10000 DESC; -- BC by end date

dbfiddle here

对于BC日期,CASE表达式默认为NULL,并且首先对它们进行排序(尚未进一步区分)。关于NULLS FIRST

接下来的4个表达式根据您的规则对BC日期进行排序。您可以为每个添加CASE WHEN upper(daterange) < 0,但由于AD日期已经完全排序,因此不会产生任何影响。也许是为了表现,但并不多。

答案 1 :(得分:0)

PostgreSQL date类型确实限于公元前4713年。但它可以达到公元5874897 - 差不多600万年!

我希望您不需要在所有600万年的范围内存储日期。你可以做的是在你的日期添加一百万(或两)年,你将适应PostgreSQL支持的范围。只要认为你已经转移日期。

例如,代替600-02-01 BC,您可以存储999400-02-01 AD(+ 1'000'000年)。

您可以从int4range切换到daterange。您将免费获得适当的分类。

您需要记住的是在显示日期之前减去已添加的年份。

相关问题