在 Postgresql 函数中添加日期中的工作日
Add business days in date in Postgresql function
我必须将 SQL 服务器过程转换为 PostgreSQL 以增加给定日期的天数。我做了一些研究并找到了一个解决方案,但它只适用于正数天数,当我传递一个负数(从给定日期后退)时它永远不会起作用。
以下是函数:
CREATE OR REPLACE FUNCTION public.add_business_day(
from_date date,
num_days integer)
RETURNS date
LANGUAGE 'sql'
COST 100
VOLATILE
AS $BODY$
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)
) s
where row_number = num_days
$BODY$;
是否有任何 fix/modification 或替代此逻辑以使其在正天数和负天数上都有效?
我相信您需要一个条件查询来生成日期系列。像这样:
select
d::date,
CASE
WHEN num_days >= 0 THEN row_number() over (order by d) - 1
ELSE row_number() over (order by d DESC) * -1 + 1
END as row_number,
extract('dow' from d)
from
generate_series(
CASE WHEN num_days >= 0 THEN current_date ELSE current_date + num_days * 2 - 5 END,
CASE WHEN num_days >= 0 THEN current_date + num_days * 2 + 5 ELSE current_date END,
'1d'
) d
这会切换 generate_series()
函数的起始值和结束值,并更改 row_number()
window 函数的顺序,以确保它以正确的顺序计算负值.
可以使用 sign()
函数从 generate_series()
函数中删除 CASE
子句。有了这个你就可以控制你要加的区间了,可以是负数,当然:
select
d::date,
CASE
WHEN num_days >= 0 THEN row_number() over (order by d) - 1
ELSE row_number() over (order by d DESC) * -1 + 1
END as row_number,
extract('dow' from d)
from
generate_series(current_date, current_date + num_days * 2 + sign(num_days)::int * 5, sign(num_days)::int * interval '1d') d
我必须将 SQL 服务器过程转换为 PostgreSQL 以增加给定日期的天数。我做了一些研究并找到了一个解决方案,但它只适用于正数天数,当我传递一个负数(从给定日期后退)时它永远不会起作用。 以下是函数:
CREATE OR REPLACE FUNCTION public.add_business_day(
from_date date,
num_days integer)
RETURNS date
LANGUAGE 'sql'
COST 100
VOLATILE
AS $BODY$
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)
) s
where row_number = num_days
$BODY$;
是否有任何 fix/modification 或替代此逻辑以使其在正天数和负天数上都有效?
我相信您需要一个条件查询来生成日期系列。像这样:
select
d::date,
CASE
WHEN num_days >= 0 THEN row_number() over (order by d) - 1
ELSE row_number() over (order by d DESC) * -1 + 1
END as row_number,
extract('dow' from d)
from
generate_series(
CASE WHEN num_days >= 0 THEN current_date ELSE current_date + num_days * 2 - 5 END,
CASE WHEN num_days >= 0 THEN current_date + num_days * 2 + 5 ELSE current_date END,
'1d'
) d
这会切换 generate_series()
函数的起始值和结束值,并更改 row_number()
window 函数的顺序,以确保它以正确的顺序计算负值.
可以使用 sign()
函数从 generate_series()
函数中删除 CASE
子句。有了这个你就可以控制你要加的区间了,可以是负数,当然:
select
d::date,
CASE
WHEN num_days >= 0 THEN row_number() over (order by d) - 1
ELSE row_number() over (order by d DESC) * -1 + 1
END as row_number,
extract('dow' from d)
from
generate_series(current_date, current_date + num_days * 2 + sign(num_days)::int * 5, sign(num_days)::int * interval '1d') d