【问题标题】:difference between timestamp in oracle in the same column同一列中oracle中的时间戳之间的差异
【发布时间】:2017-03-24 10:55:38
【问题描述】:

我在 call_event 表中有以下记录;

EVENT_ID   TIMESTAMP             EVENT   
---------  -------------------   ------
9000       03/27/2017 18.00.39   Call Start
9000       03/27/2017 18.08.44   Call END
9001       03/28/2017 14.30.27   Call Start
9001       03/28/2017 15.02.56   Call END

我应该在 oracle 中编写什么查询才能得到以下结果

EVENT_ID   TIMESTAMP             EVENT      Call Duration
---------  -------------------   ------     -------------   
9000       03/27/2017 18:00:39   Call Start  00:09:23
9000       03/27/2017 18:08:44   Call END    00:09:23
9001       03/28/2017 14.30.27   Call Start  00:33:29
9001       03/28/2017 15.02.56   Call END    00:33:29

【问题讨论】:

  • 您的通话时长似乎与时间戳差异不符。

标签: sql oracle


【解决方案1】:

Oracle 设置:

CREATE TABLE call_event ( EVENT_ID, "TIMESTAMP", EVENT ) AS
SELECT 9000, TIMESTAMP '2017-03-27 18:00:39', 'Call Start' FROM DUAL UNION ALL
SELECT 9000, TIMESTAMP '2017-03/27 18:08:44', 'Call END' FROM DUAL UNION ALL
SELECT 9001, TIMESTAMP '2017-03-28 14:30:27', 'Call Start' FROM DUAL UNION ALL
SELECT 9001, TIMESTAMP '2017-03-28 15:02:56', 'Call END' FROM DUAL;

查询:

SELECT t.*,
       MAX( "TIMESTAMP" ) OVER ( PARTITION BY EVENT_ID )
         - MIN( "TIMESTAMP" ) OVER ( PARTITION BY EVENT_ID )
         AS "Call Duration"
FROM   call_event;

输出:

EVENT_ID TIMESTAMP           EVENT      Call Duration
-------- ------------------- ---------- -------------------
    9000 2017-03-27 18:00:39 Call Start +00 00:08:05.000000
    9000 2017-03-27 18:08:44 Call END   +00 00:08:05.000000
    9001 2017-03-28 14:30:27 Call Start +00 00:32:29.000000
    9001 2017-03-28 15:02:56 Call Start +00 00:32:29.000000

【讨论】:

    【解决方案2】:

    为什么要在一次调用中使用两行?我倾向于转数据:

    select event_id, min(timestamp) as call_start_ts, max(timestamp) as call_end_ts,
           max(timestamp) - min(timestamp) as duration
    from t
    group by event_id;
    

    如果timestamp 列确实是一个时间戳,那么duration 将是一个interval。以上假设调用在结束之前开始。

    话虽如此,如果你想要单独的行,你可以用窗口函数做同样的事情::

    select event_id, min(timestamp) as call_start_ts, max(timestamp) as call_end_ts,
           (max(timestamp) over (partition by event_id) -
            min(timestamp) over (partition by event_id)
           ) as duration
    from t
    group by event_id;
    

    【讨论】:

    • 我认为某些电话记录软件可以做到这一点。他们可能会发现添加一条记录来更新一条记录更容易。
    • @Manngo 。 . .我的意思是在结果集中,而不是在源数据中。这在源数据中很有意义。
    【解决方案3】:

    这对你有帮助吗

    SELECT A.EVENT_ID, A.TIMESTAMP, A.EVENT, B.TIMESTAMP AS TIMESTAMP_END, B.EVENT AS EVENT_END, B.TIMESTAMP - A.TIMESTAMP AS DURATION
    FROM CALL_EVENT A 
    INNER JOIN  CALL_EVENT B ON A.EVENT_ID = B.EVENT_ID 
    WHERE A.EVENT = 'Call Start'
    AND B.EVENT = 'Call END'
    

    【讨论】:

      【解决方案4】:

      最棘手的部分是日期时间间隔的格式,因为在 oracle 中没有类似于TO_CHAR(...) 系列的收缩包装函数:

      SELECT event_id
           ,           to_char(extract(HOUR   FROM delta), 'fm00')
             || ':' || to_char(extract(MINUTE FROM delta), 'fm00')
             || ':' || to_char(extract(SECOND FROM delta), 'fm00') duration
        FROM (
                  SELECT event_id
                       , max(ts) - min(ts) delta
                    FROM events
                GROUP BY event_id
             )
           ;
      

      变体处理建模为DATE 列的时间戳:

      SELECT event_id
           ,           to_char(extract(HOUR   FROM delta), 'fm00')
             || ':' || to_char(extract(MINUTE FROM delta), 'fm00')
             || ':' || to_char(extract(SECOND FROM delta), 'fm00') duration
        FROM (
                  SELECT event_id
                       , numtodsinterval ( max(ts) - min(ts), 'DAY' ) delta
                    FROM events
                GROUP BY event_id
             )
           ;
      

      在 oracle 12c1 上测试。

      学分: 间隔格式取自this SO answer

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-09
        相关资源
        最近更新 更多