在PostgreSQL中查找给定月份的最后一个工作日

时间:2013-04-11 14:03:48

标签: sql postgresql greenplum

在PostgreSQL中查找给定月份的最后一个工作日

用法:如果月末是星期六或星期日,则返回上一个星期五,否则使用月末

示例:

  • 2013年3月31日属于星期日,所以返回2013年3月29日
  • 11/30/2013星期六,所以返回11/29/2013

如何在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

由于

6 个答案:

答案 0 :(得分: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 :(得分: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'

答案 2 :(得分: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 

答案 3 :(得分: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计算。

答案 4 :(得分: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;

答案 5 :(得分: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;