2

我正在尝试定位与今天匹配的上个月的日期。但是,目标日期需要基于当月剩余的相同工作日数。例如,如果今天是 14 年 6 月 6 日,那么我需要一个查询给我 14 年 5 月 7 日,因为这两个日期在各自的月份中还有 16 个工作日。另外,我正在使用 SQL Developer。

4

1 回答 1

1

有几种方法可以判断一天是工作日还是周末,但它们受 NLS 设置的约束。我在英国,因此我对 NLS_TERRITORY 的设置确定周六和周日是第 6 天和第 7 天。但是,其他地区(例如美国)将周日作为第 1 天。 了解更多

无论如何,这个查询会生成从现在到 6 月底之间的工作日:

select weekday
from ( select weekday
              , to_char(weekday,'D') as dayn
       from ( select (sysdate + level) as weekday
              from dual
              connect by level <= (last_day(sysdate) - sysdate)
            )
      )
where dayn not in ('6','7')
/ 

...这给出了这个结果集...

  8* where dayn not in ('6','7')

WEEKDAY
---------
09-JUN-14
10-JUN-14
...
26-JUN-14
27-JUN-14
30-JUN-14

16 rows selected.

SQL> 

因此,我们可以将该逻辑包装在子查询中以获取天数,并使用一些LAST_DAY()、ADD_MONTHS() 和 TRUNC() 魔术 来生成上个月的类似列表。

with curr as ( select count(*) as nod
              From
                 (
                    select weekday
                    from ( select weekday, to_char(weekday,'D') as dayn
                           from ( select sysdate + level weekday
                                  from dual
                                  connect by level <= (last_day(sysdate) - sysdate)
                                )
                          )
                    where dayn not in ('6','7')
                )
                )
    , bds as ( select trunc(add_months(sysdate, -1), 'MM') fd
                       , last_day(add_months(sysdate, -1)) ld
                from dual )
    , prev as ( select weekday
                       , row_number() over (order by weekday desc) rn
                from (
                        select fd + (level-1) weekday
                        from bds
                        connect by level <= ld-fd
                      )
                where  to_char(weekday,'D')  not in ('6','7')
                )
select prev.weekday
       , rn
from   prev
where  prev.rn <= ( select nod+1 from curr )
order by prev.weekday
/

...在五月生成以下日期范围...

 30* order by prev.weekday

WEEKDAY           RN
--------- ----------
08-MAY-14         17
09-MAY-14         16
12-MAY-14         15
...
28-MAY-14          3
29-MAY-14          2
30-MAY-14          1

17 rows selected.

SQL> 

现在,此范围与您建议的范围不匹配。那是因为圣灵。在英国,2014 年 5 月 26 日是银行假日。但是,Oracle 日期功能无法处理此类事情。因此,如果您想在计算中包括公共假期,则需要为它们创建一个参考表。我们可以像这样在子查询中包含该表:

, prev as ( select weekday
                   , row_number() over (order by weekday desc) rn
            from (
                    select fd + (level-1) weekday
                    from bds
                    connect by level <= ld-fd
                  )
            where  to_char(weekday,'D')  not in ('6','7')
            and weekday not in ( select holiday from public_holidays )
            )

...这给了我们这个结果集...

WEEKDAY           RN
--------- ----------
07-MAY-14         17
08-MAY-14         16
...
28-MAY-14          3
29-MAY-14          2
30-MAY-14          1

17 rows selected.

SQL> 
于 2014-06-08T08:56:49.433 回答