2012-04-10 46 views
21

Khi trừ timestamps giá trị trả lại là interval loại dữ liệu. Có cách nào thanh lịch để chuyển đổi giá trị này thành tổng số (milli/micro) giây trong khoảng thời gian, tức là số nguyên.Trích tổng số giây từ một kiểu dữ liệu khoảng thời gian

Sau đây sẽ làm việc, nhưng nó không phải là rất khá:

select abs(extract(second from interval_difference) 
      + extract(minute from interval_difference) * 60 
      + extract(hour from interval_difference) * 60 * 60 
      + extract(day from interval_difference) * 60 * 60 * 24 
      ) 
    from (select systimestamp - (systimestamp - 1) as interval_difference 
      from dual) 

Có một phương pháp đơn giản hơn trong SQL hoặc PL/SQL?

+1

: đâu đó tôi đã tìm thấy này ' chọn (TRUNC (SYSDATE) + out.interv - TRUNC (SYSDATE)) * 86400 từ (chọn systimestamp - (systimestamp -1) làm interv từ kép) out' –

+0

kể từ khi thêm sự trở lại của khoảng thời gian tính bằng giây vào một biến số chính xác cố định, phần phân số thứ hai bị mất trong truy vấn được đề cập trong các ý kiến ​​ –

Trả lời

18

Tôi hy vọng điều này giúp đỡ:

[email protected]> select interval_difference 
     2  ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference 
     3 from (select systimestamp - (systimestamp - 1) as interval_difference 
     4   from dual) 
     5 ; 

INTERVAL_DIFFERENCE                FRACT_SEC_DIFFERENCE 
------------------------------------------------------------------------------- -------------------- 
+000000001 00:00:00.375000                 86400,375 

Với thử nghiệm của bạn:

[email protected]> select interval_difference 
     2  ,abs(extract(second from interval_difference) + 
     3  extract(minute from interval_difference) * 60 + 
     4  extract(hour from interval_difference) * 60 * 60 + 
     5  extract(day from interval_difference) * 60 * 60 * 24) as your_sec_difference 
     6  ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference 
     7  ,round(sysdate + (interval_difference * 86400) - sysdate) as sec_difference 
     8  ,round((sysdate + (interval_difference * 86400) - sysdate) * 1000) as millisec_difference 
     9 from (select systimestamp - (systimestamp - 1) as interval_difference 
    10   from dual) 
    11/

INTERVAL_DIFFERENCE                YOUR_SEC_DIFFERENCE FRACT_SEC_DIFFERENCE SEC_DIFFERENCE MILLISEC_DIFFERENCE 
------------------------------------------------------------------------------- ------------------- -------------------- -------------- ------------------- 
+000000001 00:00:00.515000                86400,515   86400,515   86401   86400515 

[email protected]> 
+3

Tôi đã giải thích chính xác lý do tại sao nó hoạt động ở đây: http://stackoverflow.com/a/17413839/458741 – Ben

+1

Điều này không có tác dụng đối với một số giá trị của interval_difference. Ví dụ: chọn interval_difference, sysdate + (interval_difference * 86400) - sysdate như fract_sec_difference từ ( chọn systimestamp - (systimestamp - 1/3) như interval_difference từ kép ); –

3

Thật không may, tôi không nghĩ rằng có một cách thay thế (hoặc thanh lịch hơn) để tính tổng số giây từ một loại khoảng thời gian bằng pl/sql. Dưới dạng this article đề cập:

... unlike .NET, Oracle provides no simple equivalent to TimeSpan.TotalSeconds. 

do đó trích xuất ngày, giờ vv từ khoảng thời gian và nhân với giá trị tương ứng có vẻ như là cách duy nhất.

2

Dựa trên zep's answer, tôi quấn mọi thứ vào một chức năng thuận tiện cho bạn:

CREATE OR REPLACE FUNCTION intervalToSeconds( 
    pMinuend TIMESTAMP , pSubtrahend TIMESTAMP) RETURN NUMBER IS 

vDifference INTERVAL DAY TO SECOND ; 

vSeconds NUMBER ; 

BEGIN 

vDifference := pMinuend - pSubtrahend ; 

SELECT EXTRACT(DAY FROM vDifference) * 86400 
    + EXTRACT(HOUR FROM vDifference) * 3600 
    + EXTRACT(MINUTE FROM vDifference) * 60 
    + EXTRACT(SECOND FROM vDifference) 
    INTO 
    vSeconds 
    FROM DUAL ; 

    RETURN vSeconds ; 

END intervalToSeconds ; 
+2

Cảm ơn bạn, nhưng một hàm kém hiệu quả hơn SQL. Bạn sẽ mất khoảng một phần nghìn giây cho mỗi bản ghi trong chuyển đổi ngữ cảnh SQL/PL/SQL một mình. Cũng không cần phải chọn từ hai hoặc để gán kết quả cho biến, bạn có thể trả lại trực tiếp. Tôi sẽ viết cùng chức năng như thế này: http: // www.sqlfiddle.com/#!4/42d23/1. Tuy nhiên, tôi muốn nhấn mạnh rằng một chức năng không nên được sử dụng nếu có thể. – Ben

+0

Ngoài ra, bây giờ tôi đến để suy nghĩ về nó mã là của tôi ... Tôi đã hỏi nếu có một cách tốt hơn để làm điều đó! Chào mừng bạn đến với Stack Overflow :-). – Ben

6

tôi đã tìm thấy điều này để làm việc. Rõ ràng, nếu bạn làm arithmetics với timestamps chúng được chuyển đổi sang một số kiểu dữ liệu nội bộ, khi được trừ ra khỏi nhau, trả về khoảng thời gian như một số.

Dễ dàng? Vâng. Thanh lịch? Không. Hoàn thành công việc? Oh yeah.

SELECT ((A + 0) - (B + 0)) * 24 * 60 * 60 
FROM 
(
    SELECT SYSTIMESTAMP A, 
      SYSTIMESTAMP - INTERVAL '1' MINUTE B 
    FROM DUAL 
); 
+0

Điều này chỉ cho tôi toàn bộ giây. – vikingsteve

+0

Rất tiếc, đúng. Câu hỏi được hỏi một cách chính xác về vi/mili giây. Đây là một cách dễ dàng để cung cấp cho toàn bộ giây, mặc dù. – Waldo

+0

CAST (A AS DATE) tương đương với (A + 0) – Andrew

12

Một cách dễ dàng:

select extract(day from (ts1-ts2)*86400) from dual; 

Ý tưởng là để chuyển đổi giá trị khoảng vào ngày bởi lần 86400 (= 24 * 60 * 60). Sau đó trích xuất giá trị 'ngày' thực sự là giá trị thứ hai mà chúng tôi muốn.

+0

Đây là một câu trả lời đáng yêu. –

+1

Tôi đã điều chỉnh điều này để sử dụng 'trích xuất (ngày từ (ts1-ts2) * 86400 * 1000)/1000' để có độ chính xác mili giây. –

0

chọn (cast (timestamp1 như ngày) -cast (timestamp2 như ngày)) * 24 * 60 * 60)

Các vấn đề liên quan