store duration in teradata - sql

I am getting source data with duration between 2 timestamps as
Duration Start date End date Start station
14h 26min. 2sec. 12/31/2010 23:49 1/1/2011 14:15 10th & U St NW (31111)
how can I import this data ( which is in CSV file ) in Teradata database to store duration in correct data type, so that I can match it properly with the difference between start and end data?
Please help in correct approach here.
Thanks in advance

That's quite tricky.
A pure SQL based solution (without features of your ETL-tool) needs to generate data which can be safely casted.
This will modify your duration into a format which can be passed to to_dsinterval by removing unneccessary characters besides HMS (target column should be defined as INTERVAL HOUR(4) TO SECOND(0))
Cast(to_dsinterval('PT'||Upper(OTranslate(duration, ' in.ec', ''))) AS INTERVAL HOUR(4) TO SECOND(0))
Your input timestamps show single digit day/month, which Teradata doesn't support (don't aks why), the RegEx adds those missing zeroes (when the seconds are missing remove the :ss part of the format):
Cast(RegExp_Replace(start_date, '\b([0-9])\b', '0\1') AS TIMESTAMP(0) Format 'mm/dd/yyyyBhh:mi:ss')
Finally pass duration & timestamps as VarChars and apply the Casts during Insert.

Related

Issues while converting timestamp to specific timezone and then converting it to date in bigquery

I am doing just a simple conversion of timestamp column value to specific timezone and then getting the date out of it to create analytical charts based on the output of the query.
I am having the column of type timestamp in the bigquery and value for that column is in UTC. Now I need to convert that to PST (which is -8:00 GMT) and was looking straight forward to convert but I am seeing some dates up and down based on the output I get.
From the output that I was getting I took one abnormal output and wrote a query out of it as below:
select "2021-05-27 18:10:10" as timestampvalue ,
Date(Timestamp("2021-05-27 18:10:10" ,"-8:00")) as completed_date1,
Date(Timestamp("2021-05-27 18:10:10","America/Los_Angeles")) as completed_date2,
Date(TIMESTAMP_SUB("2021-05-27 18:10:10", INTERVAL 8 hour)) as completed_date3,
Date(Timestamp("2021-05-27 18:10:10","America/Tijuana")) as completed_date4
The output that I get is as below:
Based on my understanding I need to subtract 8 hours from the time in order to get the timestamp value for the timezone that I wanted and according to that completed_date3 column seems to show the correct value that should be there but if I use other timezone conversions as suggested in google documentation, the output gets changed to 2021-05-28 and I am not able to understand how that can happen.
Can anyone let me know what is the thing that I am doing wrong?
I was actually using it in a wrong way. I need to use it as below :
select "2021-05-27 18:10:10" as timestampvalue ,
Date(Timestamp("2021-05-27 18:10:10") ,"-8:00") as completed_date1,
Date(Timestamp("2021-05-27 18:10:10"),"America/Los_Angeles") as completed_date2,
Date(TIMESTAMP_SUB("2021-05-27 18:10:10", INTERVAL 8 hour)) as completed_date3,
Date(Timestamp("2021-05-27 18:10:10"),"America/Tijuana") as completed_date4
Initially I was converting that string timestamp to a specific timestamp based on the timezone and that is what I did not want.
Now if a convert a string to timestamp first without using time zone parameter and then apply timezone parameter when getting the date value out of it then it would return me correct date.
Please see the snapshot below :

How to create a table that allows a user to type a time value only [duplicate]

In one field I need to store not a datetime pair, i.e. a standard Oracle date.
01/10/2009 22:10:39
But time only
22:10:39
I think that save disk space (I have 2 million rows) or provide faster processing.
You could try the INTERVAL DAY TO SECOND data type but it won't save you any disk space ... it is very suitable for this purpose though.
create table t1 (time_of_day interval day (0) to second(0));
insert into t1 values (TO_DSINTERVAL('0 23:59:59'));
select date '2009-05-13'+time_of_day
from t1;
11 bytes though.
Your best bet would probably be storing "seconds since midnight" as a number field.
SELECT to_char( SYSDATE, 'SSSSS' ) FROM dual;
You can extract the time from a date as a string like this:
to_char(sysdate,'HH.MI.SS')
but there is no time-only data type that will help you save space.
you can use:
TO_CHAR(<DATE_COLUMN>, '<TIME_FORMAT>');
example
TO_CHAR(SYSDATE, 'HH24:MI:SS');
for time format you can check in here
You would save a few Mb of disk space(which is nothing nowadays) and you would gain next to nothing in performance.
You could use a column of NUMBER type for storing the number of seconds since midnight as suggested, just don't forget about the constraints.
(You'd probably use NUMBER(5, 0) which uses 1-3 bytes depending on the stored value, instead of a constant 7 bytes used by a DATE column)

How do you convert varchar string in ISO 8601 format 'ID:HH24:MI' into time?

I have a column in postgresql of type varchar that stores time in the format "ID:HH24:MI" and I would like to add/subtract time to it. For example, a value of "4:21:35" would translate to Thursday 9:35PM. If I wanted to add thirty minutes to it, I expect the string "4:22:05".
I tried the query below but it does not work because it returns the wrong day. I'm expecting 4:22:05 and it returns 6:22:05.
SELECT to_char(to_timestamp('4:21:35', 'ID:HH24:MI' ) + INTERVAL '30 minute', 'ID:HH24:MI');
6:22:05
How could I modify the query or change my approach to achieve the right output? I want to compare time strings in the format "ID:HH24:MI" and would like to be able to add/subtract time to those time strings. Any help would be greatly appreciated.

teradata SQL convert real to timestamp

I can't understand how to convert this type of real - 42389.520752314813 to timestamp.
I got this data from one source, but I need to convert it to normal timestamp format.
I think you have received wrong input data.
this type of timestamp is only occurring when Destination tool is excel and which has CELL as "Number" type, and during Copy-Paste of timestamp, destination field has Calculated it as Mathematical function. Please re-verify your source. I am sure about this mathematical calculation. please check the below sample of such data. So practically you cannot perform its reverse operation.
Hard to do without knowing what timestamp should be returned.
If the date is sourced from a SQL Server it might be '2016-01-22 12:29:53':
cast( date '1900-01-01' + myCol as timestamp(3))
+ (cast(86400 * (myCol mod 1) as dec(12,6)) * interval '00:00:01.000000' hour to second)
If it's from Excel it's two days earlier and you must start at '1899-12-30'

Parse time strings with different formats and compare them

I am running a query between several tables and I am running into an issue between comparing two time columns on separate tables: "rc1_time" is in a string format and "osemplog_time" is in a time format. both are time only with no date
rc1_time's contents look like this '10560684' which corresponds to HH24MISSMS
osemplog_time's contents look like 07:57:02.917455
how do I format the rc1_time into a "time format" with no date?
what are some options for comparing the two times?
I am newbie at this exposition on your answers would be welcome
below is my query
SELECT
"public".payroll_master.prm1_name,
"public".payroll_master.prm1_oe_init,
"public".receipt.rc1_init,
"public".employee_log.osemplog_ipaddress,
"public".employee_log.osemplog_event,
"public".receipt.rc1_date,
"public".employee_log.osemplog_logdate,
"public".receipt.rc1_code,
"public".employee_log.osemplog_logname,
"public".oslogname.lognm_empname,
"public".receipt.rc1_arname,
"public".receipt.rc1_arnum,
"public".receipt.rc1_time,
"public".employee_log.osemplog_logtime
FROM
"public".receipt
INNER JOIN "public".employee_log ON "public".receipt.rc1_date = "public".employee_log.osemplog_logdate
INNER JOIN "public".payroll_master ON "public".payroll_master.prm1_oe_init = "public".receipt.rc1_init
INNER JOIN "public".oslogname ON "public".oslogname.lognm_empname = "public".payroll_master.prm1_name AND "public".oslogname.lognm_name = "public".employee_log.osemplog_logname
WHERE
"public".receipt.rc1_code = 'CA'
AND
"public".employee_log.osemplog_logdate = "public".receipt.rc1_date
ORDER BY
"public".receipt.rc1_init ASC
Question as stated
You can represent a time without a date using the time data type. To convert a string from a given format into one, you can go through the to_timestamp function and then cast to time:
SELECT to_timestamp('10560684', 'HH24MISSUS')::time;
SELECT to_timestamp('07:57:02.917455', 'HH24:MI:SS.US')::time;
The basic idea is that you parse the time string using to_timestamp. The resulting timestamp will have a default date, and casting to time will remove the date, leaving only the parsed out time portion.
Assumptions:
Your hours are in 24-hour clock format (13-23 for 1 PM to 11 PM and 00 for midnight). If they are not 24 hour times, then you are missing the AM/PM designation and will need to sort that out.
The second "SS" you mention in your first pattern is actually a fractional part of seconds. If not, you'll need to adjust the pattern. If you don't care about the fractional seconds, you might consider just leaving the US and the .US off entirely and working only at the seconds level. Note that US interprets 84 to be 0.84 seconds, not actually 84 microseconds (0.000084 seconds).
Ultimately, you will need to either provide much more precise details about the format or figure out the correct format string yourself. Rather than worry about those details, I've tried to exemplify the general mechanism and leave those to you.
Comparison is then trivial. You just use PostgreSQL's operators (<, >, =, etc.):
SELECT to_timestamp('07:57:02.917455', 'HH24:MI:SS.US')::time < to_timestamp('10560684', 'HH24MISSUS')::time;
Other considerations
Be aware of time zone issues if you are working across them. You'll want to look at timetz (short form of time with time zone) or timestamptz (short form of timestamp with time zone) if you need to deal with time zones. Generally, I would recommend including time zone handling up front in case it becomes a problem later.
In this case, why not build a complete timestamp? You already have the dates: "public".receipt.rc1_date and "public".employee_log.osemplog_logdate.
You don't specify the data types, but whatever the forms of those are, it should be possible. For example, if they are actual date objects, then:
SELECT to_timestamp(to_char("public".receipt.rc1_date, 'YYYY-MM-DD')||' '||"public".receipt.rc1_time, 'YYYY-MM-DD HH24MISSMS');
If they are strings of the form 'YYYY-MM-DD', then:
SELECT to_timestamp("public".receipt.rc1_date||' '||"public".receipt.rc1_time, 'YYYY-MM-DD HH24MISSMS');
And so on. Now you have a real timestamp, which makes simple great/less than comparison much, much easier.
In my experience, it's extremely rare that you actually want to test time stamps with fractional second precision for equality. You might want a more tolerant equality check, something like SELECT t1 - t2 < interval '5 seconds', but this is really up to the application.