下一个工作日,包括Oracle SQL中的美国假期 - 没有pl / sql代码

时间:2014-10-28 19:37:45

标签: sql oracle date

阅读并尝试了很多sql代码之后,我仍然面临着这个问题。

我需要计算一个日期的第五个工作日。

我需要删除星期六' '周日'和美国假期

我有一张由美国假期组成的桌子,但是coudn能够在我的sql中正确加入它们

    BDATE       WEEKDAY_INDI
   ----------  --------------
1   6/1/2014    WEEKEND
2   6/2/2014    WEEKDAY
3   6/3/2014    WEEKDAY
4   6/4/2014    WEEKDAY
5   6/5/2014    WEEKDAY
6   6/6/2014    WEEKDAY
7   6/7/2014    WEEKEND
8   6/8/2014    WEEKEND
很明智,我可以在一张桌子/单独的桌子上获得工作日和假期

我有一个查询

select * from ODM.team 

给出了

   NAME       DOB         DOB_MONTH   DOJ         UPDATED_DATE
  ---------- ----------- ----------- ----------- --------------
1  Afnand     9/14/2000   September   2/20/2012   6/12/2014
2  Angil      10/9/2000   October      5/5/2014   6/10/2014
3  Asthwini   5/17/2000   May          4/6/2011   6/02/2014

我想计算下一个工作日UPDATED_DATE

因为我已经决定加入假期表和团队表,但它没有工作

您能否建议我如何获得下一个工作日(周末,节假日除外)。

3 个答案:

答案 0 :(得分:0)

/*
with holidays as (
  select bdate, 
         case when rnd = 1 then 'WEEKEND' else 'WEEKDAY' end weekday_indi 
  from (select trunc(sysdate) - lvl bdate, round(dbms_random.value(1,3)) rnd from (select level lvl 
         from dual connect by level <= 100)
       )
),
team as (
  select 1 name, trunc(sysdate) - 50 updated_date from dual  
) 
*/
select /* other t columns*/ name, updated_date, next5 from
(
  select /* other t columns*/t.name, t.updated_date, 
         lead(decode(h.weekday_indi, 'WEEKEND', null, h.bdate) ignore nulls, 5) 
         over (partition by name order by h.bdate) next5,
         row_number() over (partition by t.name order by h.bdate) rw
  from team t left join holidays h on t.updated_date <= h.bdate
) where rw = 1;

您可以使用Oracle分析LEAD函数WITH IGNORE NULLS选项。

lead(decode(h.weekday_indi, 'WEEKEND', null, h.bdate) ignore nulls, 5) - 如果是WEEKEND使bdate为null并找到第5个bdate,它比当前行更大(忽略空值)

  1. 使用leftqui-join查找团队表中每行等于或大于updated_date的日期
  2. 对于生成的查询中的每一行,查找下一个第5个bdate,忽略PARTITION BY中定义的组内的周末
  3. 仅获取每个组中的第一行(=团队表中的所有行)
  4. 如果HOLIDAYS表中没有bdate = updated_date,则可能无法正常工作

答案 1 :(得分:0)

我假设你有一个带有Window Aggregate方法的Oracle版本,特别是LEAD()

time_master

  BDATE   WEEKDAY_INDI
1   6/1/2014    WEEKEND
2   6/2/2014    WEEKDAY
3   6/3/2014    WEEKDAY
4   6/4/2014    WEEKDAY
5   6/5/2014    WEEKDAY
6   6/6/2014    WEEKDAY
7   6/7/2014    WEEKEND
8   6/8/2014    WEEKEND

NAME    DOB          DOB_MONTH    DOJ       UPDATED_DATE
1   Afnand  9/14/2000   September 2/20/2012 6/12/2014
2   Angil   10/9/2000   October  5/5/2014       6/10/2014
3   Asthwini    5/17/2000   May  4/6/2011       6/02/2014

以下SQL之类的东西可以帮助你入门。

SELECT t.*, LEAD(tm.BDATE, 5) OVER(PARTITION BY t.ID ORDER BY tm.BDATE)
FROM team t
INNER JOIN time_master tm 
   ON tm.BDATE >= t.UPDATED_DATE 
  AND tm.BDATE < t.UPDATED_DATE+10 --10 days to catch long weekends
  AND tm.WEEKDAY_INDI = 'WEEKDAY'

答案 2 :(得分:0)

你是纯粹的sql还是pl / sql?这是你可以在pl / sql中尝试的伪代码:

updated_date DATE; FOR i IN 1..5 outerloop updated_date := updated_date + 1; WHILE updated_date IN holidays.bdate innerloop updated_date := updated_date + 1; END innerloop; END outerloop;