如何计算 Postgres 中两个日期之间除星期日以外的天数?
Posted
技术标签:
【中文标题】如何计算 Postgres 中两个日期之间除星期日以外的天数?【英文标题】:How to count days except Sundays between two dates in Postgres? 【发布时间】:2017-06-12 03:23:21 【问题描述】:要查找两个日期之间的天数,我们可以使用以下代码:
SELECT date_part('day',age('2017-01-31','2017-01-01')) as total_days;
在上面的查询中,我们得到的是 30 而不是 31。这是为什么呢?
我还想找出星期天除了的天数。区间 ('2017-01-01', '2017-01-31')
的预期输出:
Total Days = 31
Total Days except Sundays = 26
【问题讨论】:
不相关,但是:如果“年龄”超过一个月,date_part('day',age('2017-01-31','2017-01-01'))
会给您错误的结果。例如date_part('day', age('2016-02-28','2016-01-01'))
将返回 27,尽管它应该是 58。如果您想要两个日期之间的天数,只需减去它们:date '2017-01-31' - date '2017-01-01'
谢谢@a_horse_with_no_name...会用这个
【参考方案1】:
您需要更精确地定义“两个日期之间”。包括或不包括下限和上限?一个常见的定义是包含区间的下限和排除区间的上限。另外,当下限和上限相同时,将结果定义为 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)。
相关:
How do I determine the last day of the previous month using PostgreSQL? Calculate working hours between 2 dates in PostgreSQL【讨论】:
【参考方案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');
【讨论】:
以上是关于如何计算 Postgres 中两个日期之间除星期日以外的天数?的主要内容,如果未能解决你的问题,请参考以下文章