2013-04-16 1 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를 사용하여이 논리를 임베드 할 수 있습니까?

** 편집 **

DATE_DIFFERENCE가 음 24 시간보다 클 수 있습니다. DATE_DIFFERENCE가> 24 시간이더라도 음수 인 경우 부호를 포함하고 싶지만 시간과 분의 차이를 나타낼 수도 있습니다.

+1

이 논리는 올바르지 않습니다. DATE_DIFFERENCE = 59 분 59 초 –

+0

@EgorSkriptunoff - 좋은 지점; 이 데이터 포인트를 내 대답의 예제에 추가하여 문제를 설명합니다. –

+1

오라클 기능을 생성하지 않으려는 이유는 무엇입니까? –

답변

2

쿼리에서 액세스 할 수있는 Java 함수는 SQL 함수보다 훨씬 더 많은 작업이 될 것이므로 어떤 의미인지 확실하지 않습니다. SQL 및 PL/SQL 컨텍스트를 혼합 할 때 쿼리를 사용하여 함수를 선언 할 수 없습니다.

변환이 불필요하게 복잡해 보입니다. 당신이 할 수 있습니다 :

substr(numtodsinterval(date_difference, 'DAY'), 12, 5) 

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 

이들의 전체 간격은 다음과 같습니다 : 그래서 분명 첫 번째는 00:20 반올림 것

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

는 분 라운드보다는 자릅니다로

그것은 다르게하지만 약간 동작 그러나 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

오라클 12c에서는'with ... '문 안에서 함수를 정의 할 수 있습니다. 이러한 기능은 명령문의 지속 기간 동안 만 존재합니다. 이 경우에 도움이 될 것입니다. –

+0

@a_horse_with_no_name - 예, 매우 재미 있습니다. 나는 정말로 12c를 읽기 시작할 필요가있다. 감사! –

+0

+1 @ a_horse_with_no_name, 정확히 내가 원하는 것입니다. – craig