我在PostgreSQL中有以下两个日期之间的查询。
select generate_series('2019-04-01'::timestamp, '2020-03-31', '1 month')
as g_date
我需要在每个月(即每月15号)中生成特定的日期。以下是我的查询以生成系列
DO $$
DECLARE
compdate date = '2019-04-15';
BEGIN
CREATE TEMP TABLE tmp_table ON COMMIT DROP AS
select *,
case
when extract('day' from d) <> extract('day' from compdate) then 0
when ( extract('month' from d)::int - extract('month' from compdate)::int ) % 1 = 0 then 1
else 0
end as c
from generate_series('2019-04-01'::timestamp, '2020-03-31', '1 day') d;
END $$;
SELECT * FROM tmp_table
where c=1;
;
但是,如果输入日期介于(1..29)-04-2019 ..
2019-04-25
2019-05-25
2019-06-25
2019-07-25
2019-08-25
2019-09-25
2019-10-25
2019-11-25
2019-12-25
2020-01-25
2020-02-25
2020-03-25
但如果我给出补偿:31-04-2019或30-04-2019给出投入:
2019-05-31
2019-07-31
2019-08-31
2019-10-31
2019-12-31
2020-01-31
2020-03-31
预期产量:
date flag
2019-04-01 0 ----start_date
2019-04-30 1
2019-05-31 1
2019-06-30 1
2019-07-31 1
2019-08-31 1
2019-09-30 1
2019-10-31 1
2019-11-30 1
2019-12-31 1
2020-01-31 1
2020-02-29 1
2020-03-31 0 ---end_date
如果在结果中未找到匹配的日期,则应花费该月的最后一天。即,如果在2月中未找到31,则应花费2019年2月29日,并且在4月而不是31的时间应花费2019-04- 30岁 请提出建议。
您无法通过generate_series完成所需的操作。这是由于该过程从上一个生成的值开始应用了固定的增量。您的情况1个月。现在,Postgres将成功计算从1个月到下个月的正确月末日期。例如,从1月31日起1个月的收益为2月28日(或29),因为2月31日将是无效日期,因此Postgres会处理该日期。但是,从2月28日开始的相同间隔给出了3月28日的有效日期,因此不需要进行月末调整。从那时起,Generate_Series将在每月的28号返回。同样适用于30天与31天的月份。
但是,通过对同一初始开始日期采用不同的时间间隔,您可以使用递归CTE来达到目标。如果结果日期对于该日期无效,则将进行必要的月末调整。执行以下操作:
create or replace function constant_monthly_date
( start_date timestamp
, end_date timestamp
)
returns setof date
language sql strict
as $$
with recursive date_set as
(select start_date ds, start_date sd, end_date ed, 1 cnt
union all
select (sd + cnt*interval '1 month') ds, sd, ed, cnt+1
from date_set
where ds<end_date
)
select ds::date from date_set;
$$;
-- test
select * from constant_monthly_date(date '2020-01-15', date '2020-12-15' );
select * from constant_monthly_date(date '2020-01-31', date '2020-12-31' );
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句