我正在寻找一个函数,它增加了给定日期的工作日数。
假期表
create table pyha (pyha date primary key) ;
insert into pyha values ('2018-12-24'),('2018-12-25'),('2018-12-26'),('2019-01-01');
Run Code Online (Sandbox Code Playgroud)
包含假期。周六和周日也是非工作日。
我试图创建功能
create or replace function add_business_day(from_date date, num_days int)
returns date
as $fbd$
with days as
(
select dd, extract(DOW from dd) dw
from generate_series(($1+ interval'1day')::date, ($1+ interval'1day'*$2+interval'10days')::date , '1 day'::interval) dd
)
select min(dd)::date
from days
where dw not in (6,0) and
dd not in (select pyha from pyha)
and dd>=$1+interval'1day'*$2+
interval'1day'*(select count(*) from pyha where pyha between $1+ interval'1day' and
$1+interval'1day'*$2 )
$fbd$ language sql;
Run Code Online (Sandbox Code Playgroud)
但它有时会返回不正确的结果:
add_business_day('2018-12-08',2)
Run Code Online (Sandbox Code Playgroud)
返回 2018-12-10
但正确的结果是 2018-12-11
如何在 Postgres 9.1+ 中创建这样的函数?
关键是生成一系列工作日并将它们编号为row_number():
create or replace function add_business_day(from_date date, num_days int)
returns date
as $fbd$
select d
from (
select d::date, row_number() over (order by d)
from generate_series(from_date+ 1, from_date+ num_days* 2+ 5, '1d') d
where
extract('dow' from d) not in (0, 6)
and d not in (select pyha from pyha)
) s
where row_number = num_days
$fbd$ language sql;
Run Code Online (Sandbox Code Playgroud)
测试查询的结果似乎是正确的:
select days, add_business_day('2018-12-08', days)
from generate_series(1, 20) days
days | add_business_day
------+------------------
1 | 2018-12-10
2 | 2018-12-11
3 | 2018-12-12
4 | 2018-12-13
5 | 2018-12-14
6 | 2018-12-17
7 | 2018-12-18
8 | 2018-12-19
9 | 2018-12-20
10 | 2018-12-21
11 | 2018-12-27
12 | 2018-12-28
13 | 2018-12-31
14 | 2019-01-02
15 | 2019-01-03
16 | 2019-01-04
17 | 2019-01-07
18 | 2019-01-08
19 | 2019-01-09
20 | 2019-01-10
(20 rows)
Run Code Online (Sandbox Code Playgroud)
或者,您可以在循环中查找日期:
create or replace function add_business_day_loop(from_date date, num_days int)
returns date
as $fbd$
begin
while num_days > 0 loop
from_date:= from_date+ 1;
while from_date in (select pyha from pyha) or extract('dow' from from_date) in (0, 6) loop
from_date:= from_date+ 1;
end loop;
num_days:= num_days- 1;
end loop;
return from_date;
end;
$fbd$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2032 次 |
| 最近记录: |