当前日期:2018-03-29
在SQLite中,select date('now','-1 month')
返回2018-03-01
,select date('2018-03-30','-1 month')
返回2018-03-02
,依此类推,我知道原因。
在Postgres中,以下全部返回2018-02-28
:
select date('2018-03-28') - interval '1 month'
select date('2018-03-29') - interval '1 month'
select date('2018-03-30') - interval '1 month'
select date('2018-03-31') - interval '1 month'
如何在SQLite中获得相同的行为?
答案 0 :(得分:0)
老实说 - 我认为你不能。更确切地说,我不认为你应该。
SQLite在日期arithemtic方面的工作方式不同;它不是根据人类月份计算最接近的,而是computes by rendering the date strings provided。
...请注意,“±NNN个月”通过将原始日期呈现为YYYY-MM-DD格式,将±NNN添加到MM月份值,然后对结果进行标准化。因此,例如,由“+1月”修改的数据2001-03-31最初产生2001-04-31,但4月仅有30天,因此日期归一化为2001-05-01。当原始日期是2月29日的一个变形,并且修饰符是±N年,其中N不是4的倍数时,会发生类似的效果。
这打破了完全理性的思想;从3月31日起1个月是4月30日,距离3月31日一个月(最接近)2月28日。 SQLite作弊并给出了这个的渲染和标准化版本,这通常足够接近但不准确。
所以最终,我认为你不能在这里解决这个问题。不是两个不同的DBMS解决方案以不同的方式计算日期。
这引发了为什么你开始使用不同的DBMS的问题。一个更好的解决方案是面向你想要完成的事情;如果您在SQLite中进行了测试,但生产系统是在Postgres中,那么您应该在Postgres中设置测试。
答案 1 :(得分:0)
我使用此变通方法作为子查询得到了相同的行为,其中 n 是月数。 Calendar.Date是一个日期为几年的专栏。
+ n 月:
select Date from Calendar
where strftime('%Y', Date) = strftime('%Y', 'now') and (strftime('%m', Date) - 0) = (strftime('%m', 'now') + n) and (strftime('%d', Date) = strftime('%d', 'now') or strftime('%d', Date) = strftime('%d', 'now', 'start of month','+(n+1) month', '-1 day'))
limit 1
- n 月:
select Date from Calendar
where strftime('%Y', Date) = strftime('%Y', 'now') and (strftime('%m', Date) - 0) = (strftime('%m', 'now') - n) and (strftime('%d', Date) = strftime('%d', 'now') or strftime('%d', Date) = strftime('%d', 'now', 'start of month','-(n-1) month', '-1 day'))
limit 1