2013-04-11 62 views
3

找到一個給定月份的最後一個工作日在PostgreSQL的找到最後一個工作日給定月份PostgreSQL中

用法:如果月底恰逢週六或週日,回到上週五,否則使用月末

例子:

  • 2013年3月31日適逢星期日,所以回到2013年3月29日
  • 二○一三年十一月三十○日恰逢週六,所以回到2013年11月29日

如何在PostgreSQL SQL中編寫此代碼?

我到目前爲止是這樣的(僅返回月份結束,但是當它們落在週六或週日不存在兩端月):

SELECT as_of_dt, sum(bank_shr_bal) as bank_shr_bal 
    FROM hm_101.vw_gl_bal 
WHERE as_of_dt = (date_trunc('MONTH', as_of_dt) + INTERVAL '1 MONTH - 1 day')::date 
GROUP BY 1 

感謝

+0

什麼不同類型的假期?你還需要特別處理嗎?在這種情況下,可以在適當的時間段內在每個月的最後一天填充一張小桌子。 – plundra 2013-04-11 14:59:13

+0

這是一種複雜的說法:「返回給定月份的最後一個工作日?」 – 2013-04-11 15:12:11

+0

感謝plundra。現在你讓我想我需要重新提出我的問題。我可以看到假日是如何考慮的。在我的數據世界中,導致錯過月結束日期的唯一事件是月末在星期六或星期日。 – 2013-04-11 15:24:36

回答

0

一種解決方案是使用CTE,發現每月數據的最後一天,每個月的實際最後一天

WITH s1 
as 
(
SELECT 
date_part('YEAR', as_of_dt) AOD_Year 
,date_part('MONTH', as_of_dt) AOD_Month 
,(date_trunc('MONTH', as_of_dt) + INTERVAL '1 MONTH - 1 day')::date AOD_MonthEnd 
,max(as_of_dt) AOD_LastFound 
    FROM hm_101.vw_gl_bal 
where (date_trunc('MONTH', as_of_dt) + INTERVAL '1 MONTH - 1 day')::date = '2013-03-31' 
group by 1, 2, 3 
) 
SELECT 
s1.AOD_MonthEnd 
,s1.AOD_LastFound 
,sum(v.bank_shr_bal) as bank_shr_bal 
    FROM hm_101.vw_gl_bal v 
INNER JOIN s1 
    on v.as_of_dt = s1.AOD_LastFound 
WHERE v.as_of_dt = '2013-03-29' 
GROUP BY 1, 2 
0

你想要做的是從本月的最後一天0-2天去除(你有)。

通過提取星期幾(DOW)並檢查它是0(星期日)還是6(星期六),我們知道要移除多少天。

你可以這樣說:

... - INTERVAL '1 day' * CASE date_part('DOW', last_day_of_month) 
          WHEN 0 THEN 2 -- Sunday, remove 2 days. 
          WHEN 6 THEN 1 -- Saturday, remove 1 day. 
          ELSE 0 -- Don't remove any days. 
         END 

對於可讀性的原因我並沒有包括在裏面完全last_day_of_month計算。

0

實際上,您可以在沒有CTE或存儲過程的情況下執行此操作。

select 
case 
    when extract(dow from last_day_of_month) = 0 
    then last_day_of_month - 2 
    when extract(dow from last_day_of_month) = 6 
    then last_day_of_month - 1 
    else 
    last_day_of_month 
end as last_weekday_of_month 
from(
    SELECT (date_trunc('MONTH', as_of_dt) 
    + INTERVAL '1 MONTH - 1 day')::date as last_day_of_month 
    from hm_101.vw_gl_bal 
)subquery; 
+2

你不需要'CASE'表達式,只需寫'最大(0,提取(從last_day_of_month isodow) - 5)* INTERVAL'1'D'' – 2013-04-12 01:33:44

+0

Downvoter:小心解釋? – 2013-04-17 01:53:37

+2

我已經放棄詢問,親自;駕車經過downvotes似乎是該網站的危險。 – 2013-04-17 03:34:31

1
with s as (
    select *, (date_trunc('MONTH', as_of_dt) + INTERVAL '1 MONTH - 1 day')::date last_day 
    from 
    hm_101.vw_gl_bal 
) 
SELECT 
    as_of_dt, 
    gl_acct_nbr, 
    cc_nbr, 
    sum(bank_shr_bal) as bank_shr_bal 
FROM s 
WHERE as_of_dt = (
    last_day 
    - 
    (extract(dow from last_day) = 5)::int 
    - 
    2 * (extract(dow from last_day) = 6)::int 
    ) 
GROUP BY 1,2,3 
1

A calendar table真正簡化像這些查詢的SQL。 (表「平日」,實際上是基於日曆表的視圖。它的結構應該是顯而易見的。)

select max(cal_date) 
from weekdays 
where cal_date < '2013-05-01' 

select max(cal_date) 
from weekdays 
where cal_date between '2013-04-01' and '2013-04-30' 
0
select 
case 
    when extract(dow from first_day_of_month) = 0 then first_day_of_month 
    when extract(dow from first_day_of_month) = 1 then first_day_of_month - 1 
    when extract(dow from first_day_of_month) = 2 then first_day_of_month - 2 
    when extract(dow from first_day_of_month) = 3 then first_day_of_month - 3 
    when extract(dow from first_day_of_month) = 4 then first_day_of_month - 4 
    when extract(dow from first_day_of_month) = 5 then first_day_of_month - 5 
    when extract(dow from first_day_of_month) = 6 then first_day_of_month - 6 
    end as first_weekday_of_month, 
case 
    when extract(dow from last_day_of_month) = 6 then last_day_of_month 
    when extract(dow from last_day_of_month) = 5 then last_day_of_month - 6 
    when extract(dow from last_day_of_month) = 4 then last_day_of_month - 5 
    when extract(dow from last_day_of_month) = 3 then last_day_of_month - 4 
    when extract(dow from last_day_of_month) = 2 then last_day_of_month - 3 
    when extract(dow from last_day_of_month) = 1 then last_day_of_month - 2 
    when extract(dow from last_day_of_month) = 0 then last_day_of_month - 1 
    end as last_weekday_of_month 
from(
    SELECT 
    (date_trunc('month', current_date) -'7day'::interval)::date first_day_of_month, 
    (date_trunc('month', current_date) -'1day'::interval)::date as last_day_of_month 
)subquery; 
相關問題