使用Oracle plsql在表中查找最后一个工作日

nxowjjhe  于 2023-02-21  发布在  Oracle
关注(0)|答案(2)|浏览(326)

我想从一张表中找出每个假期的最后一个工作日。例如,我有一张表,它具有以下结构:

create table t1( a char(8),
     b varchar2(40), 
     c varchar2(90), d char(8));

Insert into t1 values ('w','Feb 1', 'Tuesday','l');
....
Insert into t1 values ('H', 'Feb 3', 'sat','j');
Insert into t1 values ('H', 'Feb 4', 'sun','k');
Insert into t1 values ('H', 'Feb 5', 'mon', 'o');

我的要求是,每当我尝试为假期获取数据时(本例中为H),我需要取上一个工作日的值(在本例中为w)。简单地说,星期六和星期日的期望值应该是星期五的值。注意,insert语句将星期一也作为假日,我希望星期五的d列也作为星期一的输出。请帮助我在Oracle SQL中满足此要求。

lkaoscv7

lkaoscv71#

在Oracle 12中,您可以使用MATCH_RECOGNIZE查找所有假日,并从假日的第一天减去1天,以获得前一个最后一个工作日(假设日历表列出了每一天):

SELECT start_datetime - INTERVAL '1' DAY AS last_working_day
FROM   t1
MATCH_RECOGNIZE(
  ORDER BY datetime
  MEASURES
    FIRST(datetime) AS start_datetime
  PATTERN ( holiday+ )
  DEFINE
    holiday AS daytype = 'H'
);

其中,对于示例数据:

CREATE TABLE t1 (datetime, daytype) AS
SELECT datetime,
       CASE
       WHEN datetime - TRUNC(datetime, 'IW') >= 5
       THEN 'H'
       ELSE 'W'
       END
FROM   (
  SELECT DATE '2023-02-01' + LEVEL - 1 AS datetime
  FROM   DUAL
  CONNECT BY LEVEL <= 14
);
  • 注:2月4/5日和11/12日是2023年的周末,而不是3/4日。*

输出:
| 最后工作日|
| - ------|
| 2023年2月3日00时00分|
| 2023年2月10日00时00分|
fiddle

njthzxwz

njthzxwz2#

(设置环境;你不必这样做):

SQL> alter session set nls_date_language = 'english';

Session altered.

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

由于t1包含整个日历,并且日期被标记为working days或holidays,因此您可以使用相关子查询(查询中的第3 - 7行)来获取该表中任何其他日期之前的工作日。
您使用的列名(a,B,c,d)描述性不强,因此我尝试进行了改进:

  • statuswh
  • datum为 * 日期 *;其数据类型是(且应该是)date;如果您使用了varchar2列,请不要这样做。如果表包含两个(或更多)年份,并且您在其中存储了Feb 3-该日期属于哪一年?
  • day_name可能是多余的,因为您可以使用to_char函数从datum中获取该值,但是好吧,让我们离开它
SQL> select a.datum, a.status, a.day_name,
  2    --
  3    (select to_char(max(b.datum), 'dd.mm.yyyy, dy')
  4     from t1 b
  5     where b.datum < a.datum
  6       and b.status = 'w'
  7    ) previous_working_datum
  8  from t1 a
  9  where to_char(a.datum, 'yyyymm') = '202302'
 10  order by a.datum;

DATUM      S DAY PREVIOUS_WORKIN
---------- - --- ---------------
01.02.2023 w wed 31.01.2023, tue
02.02.2023 w thu 01.02.2023, wed
03.02.2023 w fri 02.02.2023, thu
04.02.2023 h sat 03.02.2023, fri --> holiday, so previous working day is Thursday, 02.02.2023
05.02.2023 h sun 03.02.2023, fri --> holiday
06.02.2023 h mon 03.02.2023, fri --> holiday
07.02.2023 w tue 03.02.2023, fri --> working day; its previous working day is also Thursday, 02.02.2023
08.02.2023 w wed 07.02.2023, tue
09.02.2023 h thu 08.02.2023, wed --> holiday, so previous working day is Wednesday, 08.02.2023
10.02.2023 w fri 08.02.2023, wed
11.02.2023 h sat 10.02.2023, fri
<snip>

28 rows selected.

SQL>

相关问题