Beruflich Dokumente
Kultur Dokumente
Dates, times, and timestamps in Teradata can be a little tricky. This document explains how to do various things that you may want to do. It is current through TD 12.
Preliminaries
The examples below use Teradata syntax, so they assume that you are running in BTEQ. If you are using SQL Assistant (Queryman), be sure to uncheck the option box "Allow use of ODBC SQL Extensions in queries". Changing the Date Time Format in your ODBC data source to AAA or IIA may also help. datecol means a column defined as DATE.
Dates
Literals
Date literals can be specified in many ways: -- in the same format as the column they are being compared to
where infamy_date = '12/07/1941'
Observe in the examples above that the word DATE must be used to specify the data type. To get the system date, therefore, CURRENT_DATE is a better choice than DATE.
[i.e. Thursday]
Times
Literals
The easiest way to specify a time literal is in ANSI form with a 24-hour clock:
time '15:09:17'
But in V2R5 you can use another format as long as you tell Teradata what it is:
'03-09-17PM' (time, format 'HH-MI-SST')
Alas, the first one works but the second one does not:
select cast(time '01:02:33' as time(6)); 01:02:33 --------------01:02:33.000000 select cast(time '01:02:33.456' as time(0)); *** Failure 7454 DateTime field overflow.
Truncating decimal places can be done in a UDF, but in SQL you must convert the time to a character string and back again:
select cast(cast(time '01:02:33.456' as char(8)) as time(0)); 01:02:33.456 -----------01:02:33
Time differences
First we shall address the case where your time data is defined as a number (FLOAT or DECIMAL, perhaps) in hhmmss form.
select ((time02 / 10000) * 3600 + (time02 / 100 MOD 100) * 60 + (time02 MOD 100)) ((time01 / 10000) * 3600 + (time01 / 100 MOD 100) * 60 + (time01 MOD 100)) as time_diff from dttest;
If the earlier time could fall on one day and the later time on the next day, you may have to add 86,400 (the number of seconds in one day) to the later time, like so:
select case when time02 >= time01 then ((time02 / 10000) * 3600 + (time02 / 100 MOD 100) * 60 + (time02 MOD 100)) ((time01 / 10000) * 3600 + (time01 / 100 MOD 100) * 60 + (time01 MOD 100)) else /*** Midnight has passed ***/ (((time02 / 10000) * 3600 + (time02 / 100 MOD 100) * 60 + (time02 MOD 100)) + 86400) ((time01 / 10000) * 3600 + (time01 / 100 MOD 100) * 60 + (time01 MOD 100)) end as time_diff from dttest; time_diff ------------18094.
Next we consider the case where your time data is defined as TIME(n). The usual way to take the difference of two times would be as follows:
select time02 - time01 from dttest; hour(2) to second
The above result is an interval (INTERVAL HOUR TO SECOND, to be exact). If, however, you want to compute the difference in seconds, as above, you again have to split the times up:
select (extract(hour from time02) * 3600 + extract(minute from time02) * 60 + extract(second from time02)) (extract(hour from time01) * 3600 + extract(minute from time01) * 60 + extract(second from time01)) as time_diff from dttest; time_diff ----------38363 /*** After midnight ... ***/
select case when time02 >= time01 then (extract(hour from time02) * 3600 + extract(minute from time02) * 60 + extract(second from time02)) (extract(hour from time01) * 3600 + extract(minute from time01) * 60 + extract(second from time01)) else (extract(hour from time02) * 3600 + extract(minute from time02) * 60 + extract(second from time02) + 86400) (extract(hour from time01) * 3600 + extract(minute from time01) * 60 + extract(second from time01)) end as time_diff from dttest; time_diff ----------38363
Timestamps
Literals
The easiest way to specify a timestamp literal is in ANSI form:
As before, truncating requires converting the timestamp to a character string and back again:
select cast(cast(timestamp '2008-06-24 01:02:33.456' as char(19)) as timestamp(0)); 2008-06-24 01:02:33.456 ----------------------2008-06-24 01:02:33
371 05:26:35.639649 select ts01 - ts02 day(4) to second(6) from dttest; (ts01 - ts02) DAY TO SECOND ---------------------------371 05:26:35.639649
You can also convert this interval to seconds or minutes like so:
/*** Difference in seconds ***/ select (ts02 - ts01 day(4) to second) as tsdiff, (extract(day from tsdiff) * 86400) + (extract(hour from tsdiff) * 3600) + (extract(minute from tsdiff) * 60) + extract(second from tsdiff) as sec_diff from dttest; tsdiff --------------------371 05:26:35.639649 sec_diff ----------------32073995.639649
/*** Difference in minutes ***/ select (ts02 - ts01 day(4) to minute) as tsdiff, (extract(day from tsdiff) * 1440) + (extract(hour from tsdiff) * 60) + extract(minute from tsdiff) as min_diff from dttest; *** Query completed. One row found. 2 columns returned. *** Total elapsed time was 1 second. tsdiff ----------371 05:26 min_diff ----------534566
sel ts02 - ts01 day(4) from dttest; (ts02 - ts01) DAY -----------------
371
Intervals
Literals
There are many types of intervals; see the Data Types manual for details. The key point to remember is that an interval type cannot span months, because not all months are the same length.
/* 1 year, 2 months, 5 days? */ select interval '1-02-05' year to day; *** Failure 3706 Syntax error: Invalid INTERVAL type definition. select interval '05 01:02:03' day to second; 5 01:02:03 ----------5 01:02:03
The fields in intervals are smallints, so the precision cannot be greater than 4.
select interval '1234' day; 1234 ----1234 select interval '12345' day(5); *** Failure 3706 Syntax error: Invalid INTERVAL Literal.
You can also convert combinations of fields to longer intervals by first combining them into properly formatted character strings, then casting those to intervals.
cast( cast( (smallint_hours (format '999:')) || (smallint_minutes (format '99')) as char(7) ) as interval hour to minute )
select interval '5:00:39' hour to second - interval '2:10:11' hour to second; ( 5:00:39- 2:10:11) ------------------2:50:28 select interval '5' hour - interval '10' minute; ( 5- 10) -------4:50 select interval '5:03' hour to minute - interval '14:12' minute to second; ( 5:03- 14:12) -------------4:48:48 /******** Interval * Numeric = Interval ********/ select interval '5' hour * 2; ( 5*2) -----10 select interval '4:05:06' hour to second * 3; ( 4:05:06*3) -----------12:15:18 select interval '1 02' day to hour * 4; ( 1 02*4) --------4 08 /******** Interval / Numeric = Interval ********/ select interval '5' hour / 2; ( 5/2) -----2 select interval '4:05:06' hour to second / 3; ( 4:05:06/3) -----------1:21:42 select interval '1 02' day to hour / 4; ( 1 02/4) --------0 06 /******** Numeric * Interval = Interval ********/ select 2 * interval '5' hour;
(2* 5) -----10 select 3 * interval '4:05:06' hour to second; (3* 4:05:06) -----------12:15:18 select 4 * interval '1 02' day to hour; (4* 1 02) --------4 08