2009-06-09 13 views
4

folgenden SQL-BefehlFormat Intervall mit to_char

select TO_CHAR(NVL(arg1 - arg2, TO_DSINTERVAL('0 00:00:00'))) from table1 

erzeugt ein Ergebnis der Ausführung: 000.000.000 00: 03: 01,954000.

Ist es möglich, ein spezielles Format in die to_char-Funktion einzugeben, um ein Ergebnis des Formats zu erhalten: +00 00: 00: 00.000?

Antwort

2

Ich weiß, es überhaupt nicht klug ist, noch ist es das spezielle Format-String für Sie suchen, aber diese Antwort funktioniert gegeben, dass die Ausgabe fester Länge ist:

SELECT SUBSTR(TO_CHAR(NVL(arg1 - arg2, TO_DSINTERVAL('0 00:00:00'))), 1, 1) 
     || SUBSTR(TO_CHAR(NVL(arg1 - arg2, TO_DSINTERVAL('0 00:00:00'))), 9, 2) 
     || ' ' 
     || SUBSTR(TO_CHAR(NVL(arg1 - arg2, TO_DSINTERVAL('0 00:00:00'))), 12, 12) 
    FROM table1; 

Es ist auch überspringe nur die Sekundenbruchteile, anstatt zu runden, aber ich nehme an, dass sie aus deinem Beispiel sowieso nur Nullen sind.

Dies ist eine noch größere Verlegenheit, aber ich konnte nicht widerstehen:

SELECT SUBSTR(REPLACE(TO_CHAR(NVL(arg1 - arg2, TO_DSINTERVAL('0 00:00:00'))) 
        , '0000000', '') 
      , 1, 16) 
    FROM table1; 
+0

Ihr zweiter Vorschlag funktioniert gut! auch mit HQL. Vielen dank für Deine Hilfe! –

17

könnten Sie das Ergebnis werfen, wenn Sie weniger Präzision wollen:

SQL> SELECT TO_DSINTERVAL('10 10:00:00') t_interval FROM dual; 

T_INTERVAL 
----------------------------------------------------------- 
+000000010 10:00:00.000000000 

SQL> SELECT CAST(TO_DSINTERVAL('10 10:00:00') 
    2     AS INTERVAL DAY(2) TO SECOND(3)) t_interval 
    3 FROM dual; 

T_INTERVAL 
----------------------------------------------------------- 
+10 10:00:00.000 

bearbeiten folgende OP Kommentar:

Vom Oracle Documentation (11gr1):

Intervall-Datentypen Format-Modelle nicht haben. Um ihre Darstellung anzupassen, müssen Sie daher Zeichenfunktionen wie EXTRACT kombinieren und die Komponenten verketten.

Es scheint, dass Sie manuell haben EXTRACT verwenden, um die gewünschte Ausgabe zu erreichen:

SQL> SELECT to_char(extract(DAY FROM t_interval), 'fmS99999') || ' ' || 
    2   to_char(extract(HOUR FROM t_interval), 'fm00') || ':' || 
    3   to_char(extract(MINUTE FROM t_interval), 'fm00') || ':' || 
    4   to_char(extract(SECOND FROM t_interval), 'fm00.000') 
    5 FROM (SELECT TO_DSINTERVAL('10 01:02:55.895') t_interval FROM dual) 
    6 ; 

TO_CHAR(EXTRACT(DAYFROMT_INTER 
------------------------------ 
+10 01:02:55.895 


Das ist nicht sehr elegant ist, aber es scheint, es ist der einzige Weg mit Mikrosekunden Präzision zu behandeln.

+0

Ihr Vorschlag scheint sehr nahe an der Lösung zu sein Ich brauche. Auf SQL funktioniert der Befehl ruhig gut, aber ich muss es über HQL im Ruhezustand abfragen. Mit diesem Befehl löst Hibernate die folgende Ausnahme aus: org.hibernate.hql.ast.QuerySyntaxException: erwartet CLOSE, gefunden 'DAY' –

+0

Ich habe meine Antwort bearbeitet: Ich habe nie mit HQL gearbeitet, aber vielleicht ist es der Intervall-Datentyp nicht bewusst Daher müssen Sie es manuell konvertieren. –

+0

Leider ist Hibernate davon nicht bewusst. –

6

to_char() scheint festes Format zu haben :(so REGEXP_SUBSTR kann eine Option sein, zB:

SELECT regexp_substr (TO_DSINTERVAL ('10 10:00:00'), '\d{2} \d{2}:\d{2}:\d{2}\.\d{3}') t_interval FROM dual 
1

Ein kleiner Fall von Thread Nekromantie, aber ich stieß auf diese Frage bei der Suche nach einem Intervall zu formatieren, so dass ich dachte, dass es sich lohnte, diesen Kommentar hinzuzufügen.

Aus der Oracle documentation, einen Zeitstempel auf ein Intervall führt zu einem Zeitstempel hinzugefügt, so durch einen konstanten Zeitstempel mit Nullzeitelemente hinzufügen, können Sie dann to_char format elements für Datetime den Standard verwenden ...

SELECT TO_CHAR(TIMESTAMP'1969-12-31 00:00:00' + TO_DSINTERVAL('0 00:03:01.954321'), 
    'HH24:MI:SS.FF3') FROM dual; 

jedoch gibt es eine Problem, wenn Intervalle größer als ein Tag sein könnten. Es gibt kein Formatelement für Tage, das 0 ergibt. "DDD" ist der Tag des Jahres, also im obigen Beispiel 365, oder 1 oder mehr, wenn das Intervall größer als ein Tag war. Dies ist in Ordnung, solange Ihre Intervalle weniger als 24 Stunden sind.

Sollte hinzufügen, dies ist auf 11g so kann nicht gut auf das OP anwendbar sein.

0

Sie können den letzten Teil (oder irgendein Teil) mit regulärem Ausdruck entfernen Oracle REGEXP_REPLACE tut genau das.

wählen REGEXP_REPLACE (TO_CHAR (NVL (arg1 - arg2, TO_DSINTERVAL ('0 00.00.00'))), '.. *') von table1

+1

ODER USE CAST: TO_CHAR (CAST ( AS INTERVALL TAG (2) bis ZWEIT (0))) – Leon