Rundung der Zeitstempel auf die nächste zweite
Ich habe eine Tabelle mit timestamp-Werte, und ich möchte Runde werden diese beiden Werte auf die nächste Sekunde, aber ich kann es nicht richtig funktionieren.
Meinem test-Daten und Ansätze so weit:
with v_data as
(select to_timestamp('2012-12-10 10:49:30.00000000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:30',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.46300000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:30',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.50000000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.56300000',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual
union all
select to_timestamp('2012-12-10 10:49:30.99999999',
'YYYY-MM-DD HH24:mi:ss.FF8') base_val,
to_timestamp('2012-12-10 10:49:31',
'YYYY-MM-DD HH24:mi:ss') expected
from dual)
select v1.base_val,
v1.expected,
v1.base_val + (0.5 / 86400) solution_round,
cast(v1.base_val as date) as solution_cast,
extract(second from v1.base_val) - trunc(extract(second from v1.base_val)) fractional_seconds,
v1.base_val -
(extract(second from v1.base_val) - trunc(extract(second from v1.base_val))) / 86400 solution_add
from v_data v1
Alle meine Lösungen haben einen Nachteil: Sie
- solution_round immer rundet
- solution_cast funktioniert bis auf 11gR1, aber in 11gR2 es immer rundet ab (Ursache: Oracle verändert das Verhalten - es nun schneidet, statt der Rundung, siehe https://forums.oracle.com/forums/thread.jspa?threadID=2242066 )
- solution_add Renditen 10:49:29 statt 10:49:31 für die letzten drei Zeilen
Ich denke solution_add arbeiten sollte, und ich machte einige blöde Fehler 🙂
EDIT:
Ben ' s-Lösung (siehe unten) funktioniert bei mir, aber unter Berufung auf to_char(timestamp, 'FF') scheint gefährlich zu sein - die Anzahl der Zeichen zurückgegeben, hängt von der definition des Zeitstempels.
Bin ich mit to_char(timestamp, 'FF3') statt, was scheint, um die Rückkehr Millisekunden zuverlässig.
- Müsste es nicht ein paar Klammern da?
x + 0.5 / 86400 == x + (0.5 / 86400)
- Streng genommen, die Klammern sind nicht notwendig, da die Rangfolge der / höher ist als das + . Aber ich habe Sie trotzdem machen diese anschaulicher.
- ...ja, das ist es, was ich meinte. 0.5 / 86400 keinen Sinn (
x + 0.5 / 86400 ~= x + 0.0000058
). Sollte es nicht( x + 0.5 ) / 86400
? - Nein, das sollte nicht sein. Ich möchte hinzufügen, eine halbe Sekunde (0.5 / (24*60*60), es abschneiden und verwenden, dass (eine Art "poor man ' s rounding")
- Ok, ich dachte, wir reden hier über Unix-timestamps. Oracle version klingt ziemlich geschraubt-up.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Meine bevorzugte Methode wäre die Verwendung einer CASE-Anweisung und die Tatsache, dass Sie konvertieren können, die in Bruchteilen von Sekunden zu einer Zahl, d.h.:
Dieser entfernt die Sekundenbruchteile. Dann arbeitet Sie heraus, ob der Bruchteil-Sekunden-Teil des TIMESTAMP ist 0,5 Sekunden oder mehr. Wenn ja, dann fügen Sie eine zweite, sonst nicht.
Ich finde es viel übersichtlicher und leichter zu verstehen, was Los ist. Es gibt die folgenden:
Ihrem endgültigen Ansatz funktioniert (solution_add) seine nur, dass Sie verwendet - statt +. die 11g-Verhalten ist aufgrund von einen bug-fix (in 10g und unten, plsql verwendet zu Verhalten, wie "kürzen", wenn die Umwandlung verwendet wurde, in der Erwägung, dass SQL verhielt sich so, als Runde. Oracle entschieden, PLSQL, war richtig, und geändert 11g entsprechend.
also:
obwohl ich wohl angeben, es ausdrücklich zu nehmen, die eine implizite Konvertierung von timestamp in Datum (wobei die zwielichtigen cast())
zB:
Ich bin sehr, sehr spät zu dieser Diskussion, aber nur für den Fall, dass jemand sucht, es ist eine einzeilige Antwort auf diese Frage:
Erste Stimmen, um einen TIMESTAMP(0) - es hat keine Sekundenbruchteile, so dass Sie gerundet werden.
Dann warf Sie das Ergebnis in ein DATUM
Haben Sie versucht, die Umwandlung to_date und dabei die Rundung an diesem Punkt?
http://www.java2s.com/Tutorial/Oracle/0260__Date-Timestamp-Functions/RoundingtotheNearestMinute.htm
Sollten Sie dann in der Lage sein zu konvertieren timestamp.
Offensichtlich ändern Sie die 'MI' auf Zeile 3 zu 'SS'
---UPDATE - - - -
Umwandlung in ein date-Runden auf die nächste Sekunde als der DATE-Datentyp hat eine Genauigkeit von Sekunden, sodass die Besetzung auf ein Datum, und dann gegossen, um einen Zeitstempel:
Ist dies T-SQL (nicht sicher, ob es funktioniert auf Oracle)