因为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试图保存负数,而不是关于时间顺序内容的线索。所以他们应该这样订购:
因此:
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日期的插件 - 即使我没有找到任何。
答案 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
。您将免费获得适当的分类。
您需要记住的是在显示日期之前减去已添加的年份。