2017-05-18 49 views
0

我正在写一个查询,该查询将允许我计算需要完成特定作业的日期。将时间值四舍五入到oracle的午夜之前sql

以下是我的工作和代码列表。

JOB_NO | CODES | RCVD_TIME 
ABC1 | 1 | 07-JAN-17 09:44:07 
DEF2 | 3 | 20-MAR-17 14:32:49 
GHI3 | 3 | 27-MAR-17 10:00:03 
JKL4 | 1 | 12-JAN-17 12:59:05 

现在我有几个条件来锻炼这些工作的结束日期/时间。代码3 - 如果rcvd时间在下午1点之前,那么工作要在同一天完成,直到23点59分59秒,如果rcvd时间是1点或之后工作要在第二天下午1点前完成。

我简单查询:

SELECT 
JOB_NO, CODES, RCVD_TIME, 
CASE 
    WHEN CODES = '1' 
    THEN RCVD_TIME + 1 
ELSE RCVD_TIME 
END AS TARGET 
FROM... 

这给了我(不知道如何编写代码3查询):

JOB_NO | CODES | RCVD_TIME | TARGET 
ABC1 | 1 | 07-JAN-17 09:44:07 | 08-JAN-17 09:44:07 
DEF2 | 3 | 20-MAR-17 14:32:49 | 20-MAR-17 14:32:49 
GHI3 | 3 | 27-MAR-17 10:00:03 | 27-MAR-17 10:00:03 
JKL4 | 1 | 12-JAN-17 12:59:05 | 13-JAN-17 12:59:05 

这是我想什么:

JOB_NO | CODES | RCVD_TIME | TARGET 
ABC1 | 1 | 07-JAN-17 09:44:07 | 08-JAN-17 23:59:59 
DEF2 | 3 | 20-MAR-17 14:32:49 | 21-MAR-17 13:00:00 
GHI3 | 3 | 27-MAR-17 10:00:03 | 27-MAR-17 23:59:59 
JKL4 | 1 | 12-JAN-17 12:59:05 | 13-JAN-17 23:59:59 

如果有人能就如何获得我所需的答案提出建议,我将非常感激。

在此先感谢。


编辑

有点令人沮丧,但被告知要加一个条件来考虑工作一周中的一天是1和6之间,必须确保在目标时间不落入星期日(天7)。对不起,双倍的人,只是想我会在这里添加它,以防万一错过。

+0

只是可以肯定,'RCVD_TIME'列数据类型的'date'权利,而不是'varchar' ? – Utsav

+0

这是正确的日期数据类型 – user3191160

+0

是否是1和3'CODES'的唯一可能的值?如果其他值可能,“TARGET”是如何计算的? – mathguy

回答

0

您可以在SQL中使用CASE语句来处理复杂的if-then逻辑。

-- TEST_DATA is not part of the solution 
with test_data (job_no, code, rcvd_time, target) AS (
SELECT 'ABC1',1,to_date('07-JAN-17 09:44:07','DD-MON-YY HH24:MI:SS'),to_date('08-JAN-17 09:44:07','DD-MON-YY HH24:MI:SS') FROM DUAL UNION ALL 
SELECT 'DEF2',3,to_date('20-MAR-17 14:32:49','DD-MON-YY HH24:MI:SS'),to_date('20-MAR-17 14:32:49','DD-MON-YY HH24:MI:SS') FROM DUAL UNION ALL 
SELECT 'GHI3',3,to_date('27-MAR-17 10:00:03','DD-MON-YY HH24:MI:SS'),to_date('27-MAR-17 10:00:03','DD-MON-YY HH24:MI:SS') FROM DUAL UNION ALL 
SELECT 'JKL4',1,to_date('12-JAN-17 12:59:05','DD-MON-YY HH24:MI:SS'),to_date('13-JAN-17 12:59:05','DD-MON-YY HH24:MI:SS') FROM DUAL) 
-- Actual solution begins here... 
SELECT job_no, code, rcvd_time, 
     case 
      when rcvd_time - trunc(rcvd_time) < 13/24 and code = 1 then 
       trunc(rcvd_time) + (86399/86400) + 1 
      when rcvd_time - trunc(rcvd_time) < 13/24 and code = 3 then 
       trunc(rcvd_time) + (86399/86400) 
      when rcvd_time - trunc(rcvd_time) >= 13/24 then 
       trunc(rcvd_time) + 1 + (13/24) 
     end target 
from test_data; 
+0

感谢球员们的及时回应。会给他们一个去,让你知道我如何得到。 – user3191160

0

可以使用间隔文本(所以你不需要在你的代码洒幻数):

CASE 
    WHEN code = 1 
    THEN TRUNC(rcvd_time) + INTERVAL '2' DAY - INTERVAL '1' SECOND 
    WHEN code = 3 AND TO_CHAR(rcvd_time, 'HH24') < '13' 
    THEN TRUNC(rcvd_time) + INTERVAL '1' DAY - INTERVAL '1' SECOND 
    WHEN code = 3 -- AND TO_CHAR(rcvd_time, 'HH24') >= '13' 
    THEN TRUNC(rcvd_time) + INTERVAL '1' DAY + INTERVAL '13' HOUR 
END 

进行比较的时候,你可以使用各种不同的技术:

  • TO_CHAR(rcvd_time, 'HH24') < '13'
  • EXTRACT(HOUR FROM CAST(rcvd_time AS TIMESTAMP)) < 13
  • rcvd_time < TRUNC(rcvd_time) + INTERVAL '13' HOUR
0

在下面的解决方案,我认为“特殊”处理仅适用于CODES为3,否则TARGET是第二天结束。 (这允许比1和3等CODES值...你可以适应,如果你有更多的CODES值和附加规则。)

由于所有TARGET日期时间从trunc(rcvd_time)偏移,我使用的是CASE表达只是为了确定偏移量。

select job_no, codes, rcvd_time, 
     trunc(rcvd_time) + 
     case codes when 3 then 
         case when extract (hour from cast (rcvd_time as timestamp)) < 13 
              then interval '23:59:59' hour to second 
           else interval '1 13:00:00' day to second 
           end 
        else interval '1 23:59:59' day to second 
        end as target 
from your_table; 

注意:感谢MT0显示如何从日期提取小时;我忘记extract(hour from...)只适用于时间戳。我相应地编辑了我的答案。

+0

好吧,有点令人沮丧,但被告知添加一个条件来考虑一周的工作日是在1到6之间,所以必须确保目标时间不会落入星期日(第7天)。 – user3191160

0

试试这个

select 
t.* 
,case when codes=3 
     and to_date(to_char(rcvd_time,'HH24:MI:SS'),'HH24:MI:SS') 
        >=to_date('13:00:00','HH24:MI:SS')  
    then trunc(rcvd_time)+1+(13/24) -- add 1 day and then add 13 hours 
when codes=1 
    then trunc(rcvd_time)+2-(1/(24*60*60)) --add 2 days and subtract 1 second 
else 
    trunc(rcvd_time)+1-(1/(24*60*60)) -- add 1 day and subtract 1 second 
end as target 
from tbl t; 

工作样本

with tbl (JOB_NO,CODES,RCVD_TIME) as (
select 'ABC1',1,to_date('07-JAN-17 09:44:07','DD-MON-YY HH24:MI:SS') from dual union all 
select 'DEF2',3,to_date('20-MAR-17 14:32:49','DD-MON-YY HH24:MI:SS') from dual union all 
select 'GHI3',3,to_date('27-MAR-17 10:00:03','DD-MON-YY HH24:MI:SS') from dual union all 
select 'JKL4',1,to_date('12-JAN-17 12:59:05','DD-MON-YY HH24:MI:SS') from dual) 
select 
t.* 
,case when codes=3 
     and to_date(to_char(rcvd_time,'HH24:MI:SS'),'HH24:MI:SS') 
        >=to_date('13:00:00','HH24:MI:SS')  
    then trunc(rcvd_time)+1+(13/24) -- add 1 day and then add 13 hours 
when codes=1 
    then trunc(rcvd_time)+2-(1/(24*60*60)) --add 2 days and subtract 1 second 
else 
    trunc(rcvd_timeJOB_NO,CODES,RCVD_TIME)+1-(1/(24*60*60)) -- add 1 day and subtract 1 second 
end as target 
from tbl t; 

输出

JOB_NO CODES RCVD_TIME    TARGET   
ABC1 1 07-JAN-2017 09:44:07 08-JAN-2017 23:59:59 
DEF2 3 20-MAR-2017 14:32:49 21-MAR-2017 13:00:00 
GHI3 3 27-MAR-2017 10:00:03 27-MAR-2017 23:59:59 
JKL4 1 12-JAN-2017 12:59:05 13-JAN-2017 23:59:59