要查找两个日期之间的天数,我们可以使用以下内容:
provided
在上面的查询中我们得到30作为输出而不是31.为什么会这样?
而且我还希望找到除星期日之外的天数。区间SELECT date_part('day',age('2017-01-31','2017-01-01')) as total_days;
的预期输出:
('2017-01-01', '2017-01-31')
答案 0 :(得分:4)
您需要更密切地定义“两个日期之间”。包括或排除下限和上限?一个常见的定义是 包含 下限和 排除 时间间隔的上限。另外,当下限和上限相同时,将结果定义为0。此定义恰好与日期减法正好重合。
SELECT date '2017-01-31' - date '2017-01-01' AS days_between
这个确切的定义对于排除星期日非常重要。对于给定的定义,Sun - Sun(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
, not dow
for EXTRACT()
。
要 包含 上限,只需将z - a
替换为(z - a) + 1
即可。 (由于运算符优先级,无法使用括号,但最好清楚。)
性能特征是 O(1) (常量),而不是使用 O(N)生成的集合上的条件聚合。
相关:
答案 1 :(得分:2)
您可以尝试使用generate_series
生成给定日期之间的所有日期,然后计算所需的天数。
SELECT
count(case when extract(dow from generate_series) <> 0 then 1 end) n
from generate_series('2017-01-01'::date,'2017-01-31'::date, '1 day');