在oracle sql中将时间值舍入到午夜之前

时间:2017-05-18 14:06:50

标签: oracle case

我正在编写一个查询,让我可以查看特定工作需要完成的锻炼日期。

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

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

现在我有一些条件来训练这些工作的结束日期/时间。

代码1 - 在23:59:59之前添加1天+任意时间 代码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天)。对不起双人的家伙,只是想我会在这里添加它,以防万一丢失。

4 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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

答案 2 :(得分:0)

在下面的解决方案中,我假设&#34;特殊&#34;处理仅在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...)仅适用于时间戳。我相应地编辑了我的答案。

答案 3 :(得分: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