从2010年1月1日至2030年12月31日全天,我们使用实例化视图。 有一个与标记is_working_day 0/1相关的日期字段。
我需要获取一天的前一个工作日。
示例:我们是01/01 / n,前一个工作日是31/12 / n-1。 我们是02/01 / n,上一个工作日也是31/12 / n-1。
我在这里有一些测试代码:https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=215d5e6aa6673f2273f3766f58093bc6
样本表:
DATE_D DAY_OF_WEEK_DESC_EN IS_WORKING_DAY
01-JAN-10 Friday 0
02-JAN-10 Saturday 0
03-JAN-10 Sunday 0
04-JAN-10 Monday 1
05-JAN-10 Tuesday 1
06-JAN-10 Wednesday 1
07-JAN-10 Thursday 1
08-JAN-10 Friday 1
09-JAN-10 Saturday 0
10-JAN-10 Sunday 0
select
date_d,
lag(date_d) over (order by date_d) as last_working_day,
day_of_week_desc_en
from oracle_calendar
where is_working_day = 1
预期:
DATE_D LAST_WORKING_DAY DAY_OF_WEEK_DESC_EN IS_WORKING_DAY
01-JAN-10 Friday 0
02-JAN-10 Saturday 0
03-JAN-10 04-JAN-10 Sunday 0
04-JAN-10 04-JAN-10 Monday 1
05-JAN-10 04-JAN-10 Tuesday 1
06-JAN-10 05-JAN-10 Wednesday 1
07-JAN-10 06-JAN-10 Thursday 1
08-JAN-10 07-JAN-10 Friday 1
09-JAN-10 08-JAN-10 Saturday 0
10-JAN-10 08-JAN-10 Sunday 0
基本上,我使用Oracle的LAG()函数仅获取一个工作日的前一个工作日,但是必须使用LEAD()函数获取一个封闭日的最后一个工作日。如果有连续的休息日,则必须使用与连续的休息日一样多的LEAD()函数。
我认为有一种更好的方法来获取所有连续关闭日的前一个工作日。
答案 0 :(得分:2)
您可以将LAG
与IGNORE NULLS
子句和CASE
语句一起使用:
测试数据:
CREATE TABLE oracle_calendar (
DATE_D DATE,
DAY_OF_WEEK_DESC_EN VARCHAR2(9) GENERATED ALWAYS AS ( CAST( RTRIM( TO_CHAR( DATE_D, 'Day' ) ) AS VARCHAR2(9) ) ),
IS_WORKING_DAY NUMBER(1,0)
);
INSERT INTO oracle_calendar( date_d, is_working_day )
SELECT DATE '2010-01-01', 0 FROM DUAL UNION ALL
SELECT DATE '2010-01-02', 0 FROM DUAL UNION ALL
SELECT DATE '2010-01-03', 0 FROM DUAL UNION ALL
SELECT DATE '2010-01-04', 1 FROM DUAL UNION ALL
SELECT DATE '2010-01-05', 1 FROM DUAL UNION ALL
SELECT DATE '2010-01-06', 1 FROM DUAL UNION ALL
SELECT DATE '2010-01-07', 1 FROM DUAL UNION ALL
SELECT DATE '2010-01-08', 1 FROM DUAL UNION ALL
SELECT DATE '2010-01-09', 0 FROM DUAL UNION ALL
SELECT DATE '2010-01-10', 0 FROM DUAL;
查询:
SELECT date_d,
LAG( CASE is_working_day WHEN 1 THEN date_d END, 1, NULL )
IGNORE NULLS OVER ( ORDER BY date_d) AS last_working_day,
day_of_week_desc_en,
is_working_day
FROM oracle_calendar
输出:
DATE_D | LAST_WORKING_DAY | DAY_OF_WEEK_DESC_EN | IS_WORKING_DAY :-------- | :--------------- | :------------------ | -------------: 01-JAN-10 | null | Friday | 0 02-JAN-10 | null | Saturday | 0 03-JAN-10 | null | Sunday | 0 04-JAN-10 | null | Monday | 1 05-JAN-10 | 04-JAN-10 | Tuesday | 1 06-JAN-10 | 05-JAN-10 | Wednesday | 1 07-JAN-10 | 06-JAN-10 | Thursday | 1 08-JAN-10 | 07-JAN-10 | Friday | 1 09-JAN-10 | 08-JAN-10 | Saturday | 0 10-JAN-10 | 08-JAN-10 | Sunday | 0
db <>提琴here
查询2 :
要在开始时消除所有NULL
值并使用第一个工作日:
SELECT date_d,
COALESCE(
LAG( CASE is_working_day WHEN 1 THEN date_d END, 1, NULL )
IGNORE NULLS OVER ( ORDER BY date_d),
CASE is_working_day
WHEN 1
THEN date_d
ELSE LEAD( CASE is_working_day WHEN 1 THEN date_d END, 1, NULL )
IGNORE NULLS OVER ( ORDER BY date_d)
END
) AS last_working_day,
day_of_week_desc_en,
is_working_day
FROM oracle_calendar
DATE_D | LAST_WORKING_DAY | DAY_OF_WEEK_DESC_EN | IS_WORKING_DAY :-------- | :--------------- | :------------------ | -------------: 01-JAN-10 | 04-JAN-10 | Friday | 0 02-JAN-10 | 04-JAN-10 | Saturday | 0 03-JAN-10 | 04-JAN-10 | Sunday | 0 04-JAN-10 | 04-JAN-10 | Monday | 1 05-JAN-10 | 04-JAN-10 | Tuesday | 1 06-JAN-10 | 05-JAN-10 | Wednesday | 1 07-JAN-10 | 06-JAN-10 | Thursday | 1 08-JAN-10 | 07-JAN-10 | Friday | 1 09-JAN-10 | 08-JAN-10 | Saturday | 0 10-JAN-10 | 08-JAN-10 | Sunday | 0
db <>提琴here