【问题标题】:Get number of seconds in specific duration获取特定持续时间的秒数
【发布时间】:2016-04-03 10:09:54
【问题描述】:

我有一个包含呼叫信息的表格,每个呼叫都有一个 start dateend date,日期类型为 YYYY:MM:DD HH:MI:SS 格式。

如何获得以下内容:

1- start dateend date 之间从 00:00:0007:30:00 范围内的秒数,以及超出给定范围的秒数(00:00:0007:30:00)。

2- start dateend date 之间的周五秒数。

【问题讨论】:

标签: sql oracle datetime


【解决方案1】:

与:

SELECT (end_date - start_date), ... FROM ...  

你获得天数...

与:

SELECT (end_date - start_date)*24, ... FROM ...  

你得到小时数...

并且,与:

SELECT (end_date - start_date)*24*60*60, ... FROM ...  

你获得秒数...

【讨论】:

    【解决方案2】:

    我尝试为每个调用和函数greatestleast 生成分层子查询天数:

    SQLFiddle

    with t as (
      select id, sd, ed, trunc(sd)+level-1 dt
        from calls 
        connect by trunc(sd)+level-1<=trunc(ed) 
          and prior dbms_random.value is not null and prior id = id)
    select id, sum(sec) sec, sum(fri) fri, sum(mrn) mrn, sum(sec)-sum(mrn) rest
      from (
        select id, (least(ed, dt+1)-greatest(sd, dt))*24*60*60 sec,
               case when trunc(dt) - trunc(dt, 'iw') = 4 
                    then (least(dt+1, ed) - greatest(dt, sd)) * 24*60*60 end fri,
               (least(dt+7.5/24, ed) - greatest(dt, sd)) * 24*60*60 mrn
          from t )
      group by id
    

    “星期五”的查询版本 - “非星期五早上” - “非星期五休息日”输出(在 cmets 中精确):

    with cte as (
      select id, sd, ed, trunc(sd)+level-1 dt from calls
        connect by level <= trunc(ed)-trunc(sd) + 1 
          and prior dbms_random.value is not null and prior id = id )
    select id, max(sd) start_time, max(ed) end_time, 
           sum(sec) all_seconds, sum(fri) fridays, sum(mrn) mornings,
           sum(sec) - sum(fri) - sum(mrn) rest
      from (
        select id, sd, ed, dt, (least(ed, dt+1) - greatest(sd, dt))*24*60*60 sec,
            case when dt - trunc(dt, 'iw') = 4 
                 then (least(ed, dt+1) - greatest(sd, dt))*24*60*60 else 0 end fri,
            case when dt - trunc(dt, 'iw') <> 4 and dt+7.5/24 > sd 
                 then (least(dt+7.5/24, ed) - greatest(sd, dt))*24*60*60 
                 else 0 end mrn
          from cte )
      group by id order by id
    

    样本数据和输出:

    create table calls (id number(3), sd date, ed date);
    insert into calls values (1, timestamp '2015-12-25 07:29:00', timestamp '2015-12-25 07:31:00');
    insert into calls values (2, timestamp '2015-12-24 01:00:00', timestamp '2015-12-26 23:12:42');
    insert into calls values (3, timestamp '2015-12-24 23:58:00', timestamp '2015-12-25 00:01:00');
    insert into calls values (4, timestamp '2015-12-24 07:00:00', timestamp '2015-12-25 00:01:00');
    
      ID START_TIME          END_TIME            ALL_SECONDS    FRIDAYS   MORNINGS       REST
    ---- ------------------- ------------------- ----------- ---------- ---------- ----------
       1 2015-12-25 07:29:00 2015-12-25 07:31:00         120        120          0          0
       2 2015-12-24 01:00:00 2015-12-26 23:12:42      252762      86400      50400     115962
       3 2015-12-24 23:58:00 2015-12-25 00:01:00         180         60          0        120
       4 2015-12-24 07:00:00 2015-12-25 00:01:00       61260         60       1800      59400
    

    编辑:

    【讨论】:

    • 什么是最大功能和最小功能?请你给我解释一下好吗?
    • 如果今天是星期五,您能否更新您的答案以不将秒数添加到 MRN 和 REST,例如:开始日期 = 2015-12-25 07:29:00 - 结束日期=2015 -12-25 07:31:00,我想要的答案是:(SEC=120 - FRI=120 - MRN=0 - REST=0) 我的意思是我想要从 00:00 开始的秒数:开始日期和结束日期之间的 00 到 07:30:00,如果当天不是星期五,则超出给定范围(00:00:00 到 07:30:00)的秒数
    • 我可以。但是你有盘子里的一切。唯一的就是逻辑。你可以把它放在case when 语句中。
    • 您能否更新答案,因为我尝试这样做但每次都会出现编译器错误,并且当开始数据和结束日期不包含从 00 开始的持续时间时,查询会给出错误的答案: 00:00 到 07:30:00 :(
    【解决方案3】:

    这很好用,with 子句仅用于测试:

    with a as(
    select
    TO_TIMESTAMP('122320158:00:00','MMDDYYYYHH:MI:SS') start_date,TO_TIMESTAMP('122320158:01:06','MMDDYYYYHH:MI:SS') end_date from dual
    union all
    select
    TO_TIMESTAMP('112420152:00:00','MMDDYYYYHH:MI:SS') start_date,TO_TIMESTAMP('112420152:00:53','MMDDYYYYHH:MI:SS') end_date from dual
    union all
    select
    TO_TIMESTAMP('102720157:31:00','MMDDYYYYHH:MI:SS') start_date,TO_TIMESTAMP('102720157:31:10','MMDDYYYYHH:MI:SS') end_date from dual
    ) -- until here, with clause just give sample data
    select  'before7.30' range,sum(EXTRACT(minute FROM(end_date-start_date))*60+EXTRACT(hour FROM(end_date-start_date))*3600+EXTRACT(second FROM(end_date-start_date))) as seconds
    from (
    select * from a
    )
    where start_date < trunc(start_date)+(1/24)*7.5 -- start_date<7.30
    union all
    select  'after7.30' range,sum(EXTRACT(minute FROM(end_date-start_date))*60+EXTRACT(hour FROM(end_date-start_date))*3600+EXTRACT(second FROM(end_date-start_date))) as seconds
    from (
    select * from a
    )
    where start_date >= trunc(start_date)+(1/24)*7.5 -- start_date>=7.30
    

    输出:

    before7.30  53
    after7.30   76
    

    如果您的表名为 cdr_table,只需删除 with 子句:

    select  'before7.30' range,sum(EXTRACT(minute FROM(end_date-start_date))*60+EXTRACT(hour FROM(end_date-start_date))*3600+EXTRACT(second FROM(end_date-start_date))) as seconds
    from (
    select * from cdr_table
    )
    where start_date < trunc(start_date)+(1/24)*7.5
    union all
    select  'after7.30' range,sum(EXTRACT(minute FROM(end_date-start_date))*60+EXTRACT(hour FROM(end_date-start_date))*3600+EXTRACT(second FROM(end_date-start_date))) as seconds
    from (
    select * from cdr_table
    )
    where start_date >= trunc(start_date)+(1/24)*7.5
    

    【讨论】:

      猜你喜欢
      • 2014-11-09
      • 2018-04-15
      • 1970-01-01
      • 2016-02-15
      • 2013-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      相关资源
      最近更新 更多