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的牛奶.吃完了,就準備洗碗,然後排便,再喝一大杯溫開水.然後就是帶娃,啊,多麼樸實無華 中午得自己炒菜 兩個人一葷一素,蒸個白公...
為什麼要有休息日
一張弓如果一直繃著,即使是鋼做的,也會失去彈力。同樣,不管大腦多麼聰慧,長時間地緊張,過度疲勞地思考,就會開始麻木。猶太人就是用八分的緊張和二分的鬆弛來保持最好的工作狀態。首先,一周工作六天,星期六則作為休息日停止一切工作。因為休息就是目的,所以那天他們不會大老遠去遊山玩水,等到回家已經筋疲力盡。根...