sql跳過休息日增加 減少時間

2021-10-24 19:03:02 字數 4141 閱讀 5150

oracle

給出開始時間和增/減的時間,求出跳過休息日的結束時間。

例:已知2023年9、10月日曆

若開始時間為2020-10-09,增加1天,則結束時間應為2020-10-09

若開始時間為2020-10-09,增加2天,則結束時間應為2020-10-10

若開始時間為2020-10-01,增加1天,則結束時間應為2020-10-09

若開始時間為2020-10-01,減少2天,則結束時間應為2020-09-29

需要注意的是這種需求是不可逆的,因為節假日可以作為開始時間,但是不可作為結束時間。

建立乙個表來記錄節假日資訊

create

table

`my_playday`

(`acct_day`

date

notnull

,`state`

varchar

(255

)character

set utf8 collate utf8_general_ci null

default

null

comment

'1節假日 2週末調休轉工作日 '

,primary

key(

`acct_day`

)using

btree

,index

`index_my_playday`

(`acct_day`

)using

btree

)engine

=innodb

character

set= utf8 collate

= utf8_general_ci row_format = dynamic;

建立乙個足夠大的表,一次存入數字1、2、3、4、5…

create

table sys_big_num(

num int

);

函式
create

definer

=`skip-grants user

`@`skip-grants host`

function

`f_date_add_playday`

(`_p_start_time`

datetime

,`_p_add_day`

integer

)returns

datetime

begin

declare _f_time datetime

default _p_start_time;

if _p_add_day >

9999

or _p_add_day <

-9999

then

return date_add(_p_start_time,

interval floor(_p_add_day *(5

/7))

day)

;#時間跨度過大不考慮法定節假日

endif

;if abs(_p_add_day)=0

then

return _p_start_time;

endif

;select

case

when _p_add_day >

0then

min(t1.dat)

else

max(t1.dat)

end dat

into _f_time

from

(select t1.dat,

@cot:=

case

when t1.state !=

1and

@cot

< abs(_p_add_day)

then

@cot+1

else

@cot

end flag

from

(select t1.dat,

case

when t2.state is

notnull

then t2.state

else

case

when date_format(t1.dat,

'%w')in

(6,0

)then

1else

2end

end state

from

(select date_format(date_add(_p_start_time,

interval

(t1.num -1)

*case

when _p_add_day >

0then

1else-1

endday),

'%y-%m-%d'

) dat

from sys_big_num t1 where t1.num < least(greatest(abs(_p_add_day)

*1.5

, abs(_p_add_day)

+1000),

9999

)#邊界值

) t1 left

join my_playday t2 on t1.dat = t2.acct_day

) t1,

(select

@cot:=

0) t2

order

bycase

when _p_add_day >

0then t1.dat else

null

end,

case

when _p_add_day <

0then t1.dat else

null

enddesc

) t1

where t1.flag = abs(_p_add_day)

;return _f_time;

end

呼叫方法

select f_date_add_playday(

'2020-10-1',2

);

由於函式內只有一條查詢語句,所以也可以拆出來脫離函式使用。

上文中使用的是累加的思想,有點繞,這回用直等寫乙個,**要簡單很多。

**很簡單直接發sql不寫函式了。

雖然也可以把減少天數整合到一條語句中,但是看著很亂,只寫了增加天數的。

with tab1 as

(select t1.dat,

nvl(t2.state, decode(to_char(t1.dat,

'd')

,'1'

,'1'

,'7'

,'1'

,'2'

)) state

from

(select trunc(sysdate +

level-1

,'dd'

) dat--sysdate改為增加天數

from dual connect

bylevel

<= greatest(2+

1000

, floor(2*

7/5)

)--需要乙個足夠大的數,至少要比結束時間大

) t1,

my_playday t2

where t1.dat = t2.acct_day(+)

), tab2 as

(select t1.*,

row_number(

)over

(order

by t1.dat) rn

from tab1 t1

where t1.state =2)

select t1.dat

from tab2 t1

where t1.rn =

2--增加2天

;

找到休息日

某公司軟體開發工程師孫工,作息規律為上三天班,休息一天,經常不確定休 息日是否週末,為此,請你開發乙個程式,當孫工輸入年及月,以日曆方式顯示對 應月份的休息日,用中括號進行標記.同時,統計出本月有幾天休息,輪到週末休 息有幾天.注 首次休息日是2020年2月2日 public class versi...

休息日的生活

原文 流水日記來了。起來先喝一大杯溫開水。進廚房。鍋裡燒熱水,準備煮豆絲。熱水壺燒兩壺開水。豆絲 肉丸子 大白菜,佐料 鹽 胡椒.蛋白質 煎活著煮兩個雞蛋,喝一瓶200ml的牛奶.吃完了,就準備洗碗,然後排便,再喝一大杯溫開水.然後就是帶娃,啊,多麼樸實無華 中午得自己炒菜 兩個人一葷一素,蒸個白公...

為什麼要有休息日

一張弓如果一直繃著,即使是鋼做的,也會失去彈力。同樣,不管大腦多麼聰慧,長時間地緊張,過度疲勞地思考,就會開始麻木。猶太人就是用八分的緊張和二分的鬆弛來保持最好的工作狀態。首先,一周工作六天,星期六則作為休息日停止一切工作。因為休息就是目的,所以那天他們不會大老遠去遊山玩水,等到回家已經筋疲力盡。根...