Oracle SQL 11g - 下一工作日查询

时间:2013-04-18 14:46:22

标签: oracle11g

美好的一天,我正在研究一些代码 -

1)如果在工作日的工作日(周一至周四)美国东部时区(美国)下午5:00之后和美国东部时区(美国)上午7:59:59之前提交请求,则日期将更改为下一个工作日@ 8:00 AM。

2)如果在星期五下午5:00之前和星期一之后的上午7:59:59之间提交请求的时间比上面提到的时间要长。

3)然后,代码需要检查另一个日期字段以比较“已接受”时间(在提交日期的4小时内或“新”日期)。

例如:

如果请求001已于04/17/2013 02:00 AM提交,则其新日期将为04/17/2013 08:00 AM。

如果请求002于04/17/2013 06:45 PM提交,则其新日期将为04/18/2013 08:00 AM。

如果请求003已于04/20/2013 05:45 AM(这是星期六)提交,则其新日期将是04/22/2013 08:00 AM。

我一直在将代码拼凑在一起,希望我能在最终代码中将它们整合在一起。


这是我到目前为止(日期转换代码)

            ,CASE 
        WHEN to_date(('DATE_REQUESTED'),'DAY',nls_date_language = English) in ('Friday','Saturday'))
        THEN NEXT_DAY(to_date(('DATE_REQUESTED'),'Monday') + 8 / 24)
        ELSE DATE_REQUESTED 
    END as Weekend_Converted

用于检查请求是否在4小时内被接受的代码

     SELECT RIT_Request_v.*
     ,CASE 
     WHEN DATE_ACCEPTED IS NULL THEN 'NOT ACKNOWLEDGED'
     WHEN DATE_ACCEPTED > (DATE_REQUESTED + 4 / 24) THEN 'OVER 4 HOURS'
     ELSE 'WITHIN 4 HOURS'
     END AS Acknowledgement

     FROM RIT.RIT_Request_v

     WHERE (("DATE_REQUESTED") BETWEEN trunc(sysdate, 'YYYY') AND trunc(sysdate))

正如我在下面的一条评论中所述,我更新了我的代码,现在收到“无效的标识符”错误 -

    SELECT RIT_Request_v.*
    ,CASE WHEN TO_CHAR(DATE_REQUESTED,'D') IN (1,6,7)
          THEN NEXT_DAY(DATE_REQUESTED,'MONDAY')
          ELSE DATE_REQUESTED + 1 END AS Weekend_Converted

    ,CASE WHEN DATE_ACCEPTED IS NULL THEN 'NOT ACKNOWLEDGED'
          WHEN WEEKEND_CONVERTED IS NULL THEN 'NOT ACKNOWLEDGED'
          WHEN DATE_ACCEPTED > (DATE_REQUESTED + 4 / 24) THEN 'OVER 4 HOURS'
          WHEN DATE_ACCEPTED > (Weekend_Converted + 4 / 24) THEN 'OVER 4 HOURS'
          ELSE 'WITHIN 4 HOURS' END AS Acknowledgement

    FROM RIT.RIT_Request_v

    WHERE (("DATE_REQUESTED") BETWEEN trunc(sysdate, 'YYYY') AND trunc(sysdate))

                AND FORM_ID IN         (2011,2014,5007,5036,5039,7007,10000,10001,10005,10007,10011,10024,10025,10029,10032,10033,10034,10035,10036,10037,11011,11013,11999,36001)

1 个答案:

答案 0 :(得分:0)

你的case生成weekend_converted似乎只是处理原始版本中的周末,并且似乎混淆了星期五的任何内容;更新过的日期会在第二天或下一个星期一的同一时间转移到同一时间,同时失去08:00部分和工作日的大部分时间,你根本不会改变这一天。

您在第二个版本中收到'无效标识符',因为您正在定义weekend_converted伪列,然后尝试在同一级别的查询中使用它,这是不允许的。您需要在一个级别定义,然后在外部select中引用它。

这似乎涵盖了您的规则,但我没有在任何额外日期进行测试:

select r.*,
    case
        when to_char(date_requested, 'DY',
                'NLS_DATE_LANGUAGE=English') in ('SAT', 'SUN')
            or (to_char(date_requested, 'DY',
                'NLS_DATE_LANGUAGE=English') = 'FRI'
                and extract(hour from cast(date_requested as timestamp)) >= 17)
        then trunc(next_day(date_requested, 'MON')) + interval '8' hour
        when extract(hour from cast(date_requested as timestamp)) >= 17
        then trunc(date_requested) + interval '1' day + interval '8' hour
        when extract(hour from cast(date_requested as timestamp)) < 8
        then trunc(date_requested) + interval '8' hour
        else date_requested
    end as clock_start
from rit_request_v r;

虽然强迫NLS_DATE_LANGUAGE是一个好主意,如果你不知道它将在哪里运行,next_day函数要求day参数是用你的本地语言,所以你要最好不要为整个会话而不是按功能设置它。

无论如何,这给出了:

DATE_REQUESTED   DATE_ACCEPTED       FORM_ID CLOCK_START
---------------- ---------------- ---------- ----------------
2013-04-17 02:00 2013-04-17 11:59       5007 2013-04-17 08:00
2013-04-17 18:45 2013-04-18 11:59       5007 2013-04-18 08:00
2013-04-13 05:45                        5007 2013-04-15 08:00

然后,您可以将其用作内联视图或CTE:

with t as (
select r.*,
    case
        when to_char(date_requested, 'DY',
                'NLS_DATE_LANGUAGE=English') in ('SAT', 'SUN')
            or (to_char(date_requested, 'DY',
                'NLS_DATE_LANGUAGE=English') = 'FRI'
                and extract(hour from cast(date_requested as timestamp)) >= 17)
        then trunc(next_day(date_requested, 'MON')) + interval '8' hour
        when extract(hour from cast(date_requested as timestamp)) >= 17
        then trunc(date_requested) + interval '1' day + interval '8' hour
        when extract(hour from cast(date_requested as timestamp)) < 8
        then trunc(date_requested) + interval '8' hour
        else date_requested
    end as clock_start
from rit_request_v r
where date_requested between trunc(sysdate, 'YYYY') and trunc(sysdate)
and form_id in (2011, 2014, 5007, 5036, 5039, 7007, 10000, 10001, 10005, 10007, 10011, 10024, 10025, 10029, 10032, 10033, 10034, 10035, 10036, 10037, 11011, 11013, 11999, 36001)
)
select t.*,
    case
        when date_accepted is null then 'NOT ACKNOWLEDGED'
        when date_accepted > (clock_start + interval '4' hour)
        then 'OVER 4 HOURS'
        else 'WITHIN 4 HOURS'
    end as acknowledgement
from t;

给出了:

DATE_REQUESTED   DATE_ACCEPTED       FORM_ID CLOCK_START      ACKNOWLEDGEMENT
---------------- ---------------- ---------- ---------------- ----------------
2013-04-17 02:00 2013-04-17 11:59       5007 2013-04-17 08:00 WITHIN 4 HOURS
2013-04-17 18:45 2013-04-18 11:59       5007 2013-04-18 08:00 WITHIN 4 HOURS
2013-04-13 05:45                        5007 2013-04-15 08:00 NOT ACKNOWLEDGED

我可以参考clock_start,因为它是在较低级别定义的,在本例中是在CTE中。

您会注意到我的日期与您的日期格式完全不同。通常我会说你应该将这些字段包装在to_char()中以供显示,但是(a)不清楚这是否会在SQL * Plus或任何地方显示,或者是否会提供其他内容并且应该保留作为日期;如果您确实改变了会话以检查NLS_DATE_LANGUAGE,那么您可以在那里设置NLS_DATE_FORMAT。再取决于你在运行它的单桅帆船。

您可能还会在{错误级别}对sysdate进行检查。事实上,它包括今天08:00 clock_start的任何一个,因为它正在调整预调整时间。如果您将其移到外部select,则可以检查clock_start是否在该日期范围内。当然,你也可能故意这样做过。

希望有帮助...