在雪花

发布于 2025-02-05 18:26:21 字数 527 浏览 1 评论 0原文

我想添加否。到日期领域的工作日。

以下是我的逻辑,如果一天在星期一和没有的话,这是不起作用的。天数超过5

dateadd(DAY, 
        (iff(dayofweek(to_date(Start_Date_Column) ) = 1, 0 ,
(TRUNCATE(((dayofweek(to_date(Start_Date_Column)) + No_DAYS - 1)/5)) * 2)) + No_DAYS) , to_date(Start_Date_Column)); 

。对于以下情况

 select
         
          dateadd(DAY, 
        (iff(dayofweek(to_date('2021-01-04') ) = 1, 0 ,
(TRUNCATE(((dayofweek(to_date('2021-01-04')) + 5 - 1)/5)) * 2)) + 5) , to_date('2021-01-04'))
         

I'm trying to add no. of business days to a date field.

Below is my logic, this is not working if day falls on Monday and if no. of days are more than 5.

dateadd(DAY, 
        (iff(dayofweek(to_date(Start_Date_Column) ) = 1, 0 ,
(TRUNCATE(((dayofweek(to_date(Start_Date_Column)) + No_DAYS - 1)/5)) * 2)) + No_DAYS) , to_date(Start_Date_Column)); 

e.g.. For the below scenario the date is moving to 2021-01-09(which is Saturday) instead of monday(2021-01-11)

 select
         
          dateadd(DAY, 
        (iff(dayofweek(to_date('2021-01-04') ) = 1, 0 ,
(TRUNCATE(((dayofweek(to_date('2021-01-04')) + 5 - 1)/5)) * 2)) + 5) , to_date('2021-01-04'))
         

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

混吃等死 2025-02-12 18:26:21

在将特定的工作日添加到日期之后,递归CTE将获得下一个工作日。

WITH RECURSIVE
biz_day (rown, dt) AS
(
SELECT 1,'2022-05-07'::date
union all
SELECT
case when dayname(dateadd(day,1,dt)) not in ('Sat','Sun')
then rown+1
else rown end ,
dateadd(day,1,dt)
from biz_day where rown <= $No_DAYS
)
SELECT min(dt) orig_dt,max(dt) nxt_biz_date FROM biz_day;
orig_dtnxt_biz_date
2022-05-072022-05-20

原始表 -
列next_dy将根据特定天数(例如10)

select * from dates;
DYNEXT_DY
2022-05-05NULL
2022-05-09NULL
2022-05-11NULL
2022-142022-05-14 NAULL
NULL 2022-05-05-05-05-05-05-05-05-05-05- 15NULL
2022-05-17null
2022-05-27NULL

(UDF)函数创建,包括递归CTE,用于获取下一个BIZ Day-

CREATE OR REPLACE FUNCTION next_b_date(dt date,no_day number)
RETURNS date
LANGUAGE SQL
AS
$
WITH RECURSIVE
biz_day (rown, cte_dt) AS
(
SELECT 1,dt
union all
SELECT
case when dayname(dateadd(day,1,cte_dt)) not in ('Sat','Sun')
then rown+1
else rown end ,
dateadd(day,1,cte_dt)
from biz_day where rown <= no_day
)
SELECT max(cte_dt) nxt_biz_date FROM biz_day
$;

匿名块来调用函数和更新源表 -

EXECUTE IMMEDIATE $
DECLARE
  p_dt date;
  n_dt date;
  no_days number;
  c1 CURSOR FOR SELECT dy FROM dates;
BEGIN
 
  for record in c1 do
  p_dt:=record.dy;
  no_days:=10;
  n_dt:=(select next_b_date(:p_dt,:no_days));
  update dates set next_dy = :n_dt where dy=:p_dt;
  end for;
  RETURN 0;
END;
$
;

运行更新后表 -

select * from dates;
DYNEXT_DY NEXT_DY
2022-05-- 052022-05-19
2022-05-092022-05-23
2022-05-112022-05-25
2022-05-142022-05-27 2022-27
2022-05-15 20222-2022-272022-27
2022-27 2022-05-- 也可以使用以下172022-05-31
2022-05-272022-06-10

,也可以使用,它几乎没有硬编码
即乘以乘以3的天数,三天在几天内添加额外的时间
(弥补中级SAT/SUN)以获取工作日。

set no_days=11;

update dates dt1 set next_dy = dt2.n_dy from
(
with cte1 as
(select row_number() over (partition by dy order by seq4()) rn,dy,
dateadd(day,rn,dy) day1 from dates, 
table(generator(rowcount=>$no_days*3))), cte2 as
(select row_number() over (partition by dy order by seq4()) rn,dy,day1 
from cte1 where dayname(day1) 
not in ('Sat','Sun') )
select dy,max(day1) n_dy from cte2 where rn<=$no_days 
group by dy order by dy
) dt2
where dt1.dy = dt2.dy;

更新后表 -

select * from dates;
dynext_dy
2022-05-052022-05-20
2022-05-092022-05-24
2022-05-112022-05-26
2022-05-05-142022-05-05-05-05-30
2022-05-05-05--05--05--05--05--05--05-- 152022-05-30
2022-05-172022-06-01
2022-05-272022-06-13

旧 - 解决方案(无效)添加天数并搬到下周一 -

要获得下一个工作日,请检查是否添加后的第二天是星期六或阳光,如果是这样,请使用函数next_day

与某些test-data查询:

with date_cte(bizday) as
(select * from values
('2022-05-05'::date),
('2022-05-11'::date),
('2022-05-14'::date),
('2022-05-15'::date),
('2022-05-21'::date),
('2022-05-27'::date)
)
select bizday orig_date,dayname(bizday) orig_day,
$No_DAYS No_days,
dateadd(day,$No_DAYS,bizday) next_day,
case when dayname(dateadd(day,$No_DAYS,bizday)) = 'Sat'
then next_day(dateadd(day,$No_DAYS,bizday),'Monday')
when dayname(dateadd(day,$No_DAYS,bizday)) = 'Sun'
then next_day(dateadd(day,$No_DAYS,bizday),'Monday')
else dateadd(day,$No_DAYS,bizday) end next_b_day,
dayname(next_b_day) next_b_dayname
from date_cte;
orig_dateorig_dayno_daysnos_daynext_day next_b_b_daynext_b_day next_b_dayname
2022-05-05thu102022-05-15-15-15-15-15-15-152022-05-16MON
2022-05-11WED102022-05-212022-05-23MON
2022-05-14SAT102022-05-242022-05-24SAT
​-05-252022-05-25WED
2022-05-21SAT102022-05-312022-05-31TUE
2022-05-27FRI102022-06-06-06 2022-062022-06-06MON

参考href =“ https://docs.snowflake.com/en/sql-reference/functions-date time.html#supported-date-date-and-time-parts“ rel =“ nofollow noreferrer”> date noreferrer“> date time

此外,您可能需要在此处添加更多信息,因为可以改变工作日的定义。

Recursive CTE to get next business day, after adding specific number of business days to a date.

WITH RECURSIVE
biz_day (rown, dt) AS
(
SELECT 1,'2022-05-07'::date
union all
SELECT
case when dayname(dateadd(day,1,dt)) not in ('Sat','Sun')
then rown+1
else rown end ,
dateadd(day,1,dt)
from biz_day where rown <= $No_DAYS
)
SELECT min(dt) orig_dt,max(dt) nxt_biz_date FROM biz_day;
ORIG_DTNXT_BIZ_DATE
2022-05-072022-05-20

Original table -
Column next_dy to be modified with next business day, based on specific number of days (e.g. 10)

select * from dates;
DYNEXT_DY
2022-05-05NULL
2022-05-09NULL
2022-05-11NULL
2022-05-14NULL
2022-05-15NULL
2022-05-17NULL
2022-05-27NULL

(UDF) Function creation including recursive CTE for getting next biz day -

CREATE OR REPLACE FUNCTION next_b_date(dt date,no_day number)
RETURNS date
LANGUAGE SQL
AS
$
WITH RECURSIVE
biz_day (rown, cte_dt) AS
(
SELECT 1,dt
union all
SELECT
case when dayname(dateadd(day,1,cte_dt)) not in ('Sat','Sun')
then rown+1
else rown end ,
dateadd(day,1,cte_dt)
from biz_day where rown <= no_day
)
SELECT max(cte_dt) nxt_biz_date FROM biz_day
$;

Anonymous Block to call function and update source table -

EXECUTE IMMEDIATE $
DECLARE
  p_dt date;
  n_dt date;
  no_days number;
  c1 CURSOR FOR SELECT dy FROM dates;
BEGIN
 
  for record in c1 do
  p_dt:=record.dy;
  no_days:=10;
  n_dt:=(select next_b_date(:p_dt,:no_days));
  update dates set next_dy = :n_dt where dy=:p_dt;
  end for;
  RETURN 0;
END;
$
;

Table after running the update -

select * from dates;
DYNEXT_DY
2022-05-052022-05-19
2022-05-092022-05-23
2022-05-112022-05-25
2022-05-142022-05-27
2022-05-152022-05-27
2022-05-172022-05-31
2022-05-272022-06-10

Below can also be used, which has little-bit of hard-coding
i.e. multiply number of days with 3 to go bit over extra in days
(to compensate for intermediate sat/sun) for fetching business days.

set no_days=11;

update dates dt1 set next_dy = dt2.n_dy from
(
with cte1 as
(select row_number() over (partition by dy order by seq4()) rn,dy,
dateadd(day,rn,dy) day1 from dates, 
table(generator(rowcount=>$no_days*3))), cte2 as
(select row_number() over (partition by dy order by seq4()) rn,dy,day1 
from cte1 where dayname(day1) 
not in ('Sat','Sun') )
select dy,max(day1) n_dy from cte2 where rn<=$no_days 
group by dy order by dy
) dt2
where dt1.dy = dt2.dy;

Table after update -

select * from dates;
DYNEXT_DY
2022-05-052022-05-20
2022-05-092022-05-24
2022-05-112022-05-26
2022-05-142022-05-30
2022-05-152022-05-30
2022-05-172022-06-01
2022-05-272022-06-13

Old - solution (not valid) to add days and move to next Monday -

To get next business day, check if day after adding is sat or sun and if so, get to next Monday using function next_day

Query with some test-data:

with date_cte(bizday) as
(select * from values
('2022-05-05'::date),
('2022-05-11'::date),
('2022-05-14'::date),
('2022-05-15'::date),
('2022-05-21'::date),
('2022-05-27'::date)
)
select bizday orig_date,dayname(bizday) orig_day,
$No_DAYS No_days,
dateadd(day,$No_DAYS,bizday) next_day,
case when dayname(dateadd(day,$No_DAYS,bizday)) = 'Sat'
then next_day(dateadd(day,$No_DAYS,bizday),'Monday')
when dayname(dateadd(day,$No_DAYS,bizday)) = 'Sun'
then next_day(dateadd(day,$No_DAYS,bizday),'Monday')
else dateadd(day,$No_DAYS,bizday) end next_b_day,
dayname(next_b_day) next_b_dayname
from date_cte;
ORIG_DATEORIG_DAYNO_DAYSNEXT_DAYNEXT_B_DAYNEXT_B_DAYNAME
2022-05-05Thu102022-05-152022-05-16Mon
2022-05-11Wed102022-05-212022-05-23Mon
2022-05-14Sat102022-05-242022-05-24Tue
2022-05-15Sun102022-05-252022-05-25Wed
2022-05-21Sat102022-05-312022-05-31Tue
2022-05-27Fri102022-06-062022-06-06Mon

Refer for date-time

Also, you might need to add more here as the definition of a business day can be varied.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文