您需要更紧密地定义“两个日期之间”。下限和上限是否包括在内?一个常见的定义是包括一个区间的下限,而排除一个区间的上限。另外,当上下限相同时,将结果定义为0。这个定义恰好与日期减法相吻合。
SELECT date '2017-01-31' - date '2017-01-01' AS days_between
这个确切的定义对于排除星期日非常重要。对于给定的定义,从星期日到星期日(1周后)的时间间隔不包括上限,因此只能减去1个星期日。
interval in days | sundays 0 | 0 1-6 | 0 or 1 7 | 1 8-13 | 1 or 2 14 | 2 ...
7天的间隔始终包括一个星期日。
我们可以用一个简单的整数除法(days / 7)得到最小结果,该结果将被截断。
剩余的1-6天的额外星期日取决于间隔的第一天。如果是星期天,宾果游戏;如果是星期一,那太糟了。等等,我们可以从中得出一个简单的公式:
SELECT days, sundays, days - sundays AS days_without_sundays FROM ( SELECT z - a AS days , ((z - a) + EXTRACT(isodow FROM a)::int - 1 ) / 7 AS sundays FROM (SELECT date '2017-01-02' AS a -- your interval here , date '2017-01-30' AS z) tbl ) sub;
适用于任何给定的时间间隔。
注意:isodow
,不适dow
用于EXTRACT()
。
要包含上限,只需将替换z - a
为(z - a) + 1
。(由于运算符的优先级,本来可以没有括号地工作,但是最好弄清楚。)
性能特征是O(1)(常数),与O(N)生成的集合上的条件集合相反。
有关:
如何使用PostgreSQL确定上个月的最后一天?
计算PostgreSQL中两个日期之间的工作时间