2013-04-16 46 views
0

我想用HH:MM格式格式化部分日期(兩個日期之間的差異)。在SQL中嵌入'ad hoc'函數

要做到這一點,我組裝以下邏輯:

LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' || LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')) 

我需要這樣的邏輯應用到的間隔數,所以這將是很好的使用功能DRY關鍵的東西。

有沒有辦法在SQL語句中嵌入這個邏輯(可能使用Java)而不必求助於創建Oracle函數?

** **編輯

的DATE_DIFFERENCE可以是負的和大於24小時。如果是負值,我希望包含該符號,但即使DATE_DIFFERENCE> 24小時,也表示小時和分鐘的差異。

+1

此邏輯錯誤,例如當DATE_DIFFERENCE = 59分59秒 –

+0

@EgorSkriptunoff - 好點;我在回答中將這個數據點添加到了示例中以證明問題。 –

+1

爲什麼你想避免創建oracle函數? –

回答

2

從查詢訪問的Java函數比SQL函數的工作量要多得多,所以我不完全確定你的意思。您不能像查詢混合SQL和PL/SQL上下文一樣使用查詢來聲明函數。

您的轉換看起來不必要的複雜;你可以這樣做:

numtodsinterval function需要你的時間差並將其轉換爲一個間隔的數據類型,以及substr得到覆蓋小時和分鐘一節。

稍微表現雖然有所不同,因爲它會截斷而不是相反分鐘:

with tmp as (
    select to_date('2013-04-11 13:17:15', 'YYYY-MM-DD HH24:MI:SS') 
     - to_date('2013-04-11 12:57:38', 'YYYY-MM-DD HH24:MI:SS') 
     as date_difference 
    from dual 
    union all 
    select to_date('2013-04-11 11:11:35', 'YYYY-MM-DD HH24:MI:SS') 
     - to_date('2013-04-10 22:40:45', 'YYYY-MM-DD HH24:MI:SS') 
    from dual 
    union all 
    select to_date('2013-04-11 00:59:59', 'YYYY-MM-DD HH24:MI:SS') 
     - to_date('2013-04-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 
    from dual 
) 
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' || 
     LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')), 
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5) 
from tmp; 

LTRIM(T SUBSTR(NUMTODSINTERV 
------- -------------------- 
00:20 00:19 
12:31 12:30 
00:00 00:59 

對於那些全間隔爲:

NUMTODSINTERVAL(DATE_DIFFERENCE,'DAY') 
--------------------------------------------------------------------------- 
+000000000 00:19:37.000000000 
+000000000 12:30:50.000000000 
+000000000 00:59:59.000000000 

所以很明顯第一個將四捨五入到00:20 ,但截斷爲00:19。正如Egor Skriptunoff在評論中指出的那樣,你對第三個計算的計算給了你一個不正確的答案,這就是我現在包含它的原因。

這將全面分鐘,但時間長一點:

to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI') 

的文字,在那裏我使用date '2001-01-01'使用實際的日期,也沒有關係,它可以是任何一天,你例如可以使用trunc(sysdate)。它只是允許您將差異轉換回DATE對象,然後您可以使用內置的round(date) function。對於比較:

with tmp as (...) 
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' || 
     LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')), 
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5), 
    to_char(trunc(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI'), 
    to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI') 
from tmp; 

LTRIM(T SUBSTR(NUMTODSINTERV TO_CH TO_CH 
------- -------------------- ----- ----- 
00:20 00:19    00:19 00:20 
12:31 12:30    12:30 12:31 
00:00 00:59    00:59 01:00 

這些都不其實是給予你想要的東西,嵌入式特設功能,但至少如果邏輯更清晰,然後再使用它可能不是這樣的擔心。用SQL函數包裝它仍然可能不是一個可怕的選擇。

+4

您可能會對Oracle 12c允許您在'with ...'語句中定義函數感興趣。這些功能只會在聲明期間存在。在這種情況下會派上用場。 –

+0

@a_horse_with_no_name - 是的,這非常有趣。我真的需要開始閱讀12c。謝謝! –

+0

+1 @a_horse_with_no_name,這正是我想要的。 – craig