如何在Postgres的两个日期之间计算除星期日以外的天数?

时间:2017-01-26 15:36:57

标签: postgresql postgresql-9.3 date-arithmetic

要查找两个日期之间的天数,我们可以使用以下内容:

provided

在上面的查询中我们得到30作为输出而不是31.为什么会这样?
而且我还希望找到星期日之外的天数。区间SELECT date_part('day',age('2017-01-31','2017-01-01')) as total_days; 的预期输出:

('2017-01-01', '2017-01-31')

2 个答案:

答案 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');