
印象這是很多年前一個計算周期的問題,主要是利用 generate_series 產生出當月日期,搭配 case 標記邏輯規則產製出該月可能被開 Combo 的狀態。
需要注意運用 case 時具有順序性,以本案例而言 danger 必須排在 warning 之上,否則會造成月底時應當標記 danger 卻錯標 warning 的狀況。
GY 同事可能開 Combo 的請假週期規則:每逢週一、五為警告 (warning) ,逢月底為危險 (danger) 其他則為正常上班 (job) 及假日 (vacation)
其他關鍵 isodow 將一週定義為 1-7 從週一開始計算
取得當月最後五天則為:先取得下月月初接著減去五日
1 2 3 4
| select date_part( 'isodow' , current_date);
select ('2020-10-01'::date + interval '1 month' - interval '5 day')::timestamp then 'danger';
|
完整範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| select n::date days , date_part( 'isodow' , n) isodow , to_char(n , 'DY') weekname , case when date_part( 'isodow' , n) in (6,7) then 'vacation' when n >= ('2020-10-01'::date + interval '1 month' - interval '5 day')::timestamp then 'danger' when date_part( 'isodow' , n) in (1,5) then 'warning' else 'job' end status from generate_series( '2020-10-01'::timestamp , ('2020-10-01'::date + interval '1 month' - interval '1 day')::timestamp , interval '1 day' ) n
|
若不使用 generate_series 產生日期方法如下,比較特別是可以使用 limit 進行區間限制亦可產生以天數為單位的日期序列
1 2 3 4 5 6 7 8 9 10
| with recursive tally(d) as( select '2020-10-01'::timestamp d union all select d + interval '1 day' from tally ) select * from tally limit to_char(('2020-10-01'::date + interval '1 month' - interval '1 day') , 'DD')::int
|