Subtract time using Oracle PL/SQL - sql

I'm creating a report using BI Publisher. Now, I want is to subtract 4 hours in the date. For example, the date I get in the oracle database is below,
2019-09-23T10:09:34.054+00:00
Now I want it to return in report using sql is,
2019-09-23T06:09:34.054+00:00
How can I do that?
Thanks!

Use INTERVAL?
SELECT ts - INTERVAL '4' HOUR
FROM yourTable;
Demo
If your source data is actually text, and not a bona fide timestamp column, then you may use TO_TIMESTAMP_TZ to first do a conversion:
SELECT
TO_TIMESTAMP_TZ(REPLACE(s, 'T', ' ') 'YYYY-MM-DD HH24:MI:SS.FF3TZH:TZM') AS ts_original,
TO_TIMESTAMP_TZ(REPLACE(s, 'T', ' ') 'YYYY-MM-DD HH24:MI:SS.FF3TZH:TZM') - INTERVAL '4' HOUR AS ts_offset
FROM yourTable;

You just need to subtract a fraction of time. Like this for 4 hours ago:
select sysdate-1/6 from dual;

Related

How to add minutes to a DATE type using only to_char and to_date?

As mentioned in title, I am looking for way to add minutes onto a DATE type attribute without converting it to another data type.
( SELECT to_char(event_starttime, 'HH:MI:SS') + to_char('00:06:44', 'HH:MI:SS')
FROM
event
WHERE
event_id = (
SELECT
event_id
FROM
event
WHERE
carn_date = to_date((
SELECT
carn_date
FROM
carnival
WHERE
carn_name = 'RM Autumn Series Caulfield 2022'
), 'DD/MM/YYYY')
AND eventtype_code = '21K'
)
);
But it does not seem to be working. Converting to other data type is not possible and I can only use to_char and to_date to do it.
Once again, thank you for your help
To add, for example, 15 minutes to a date just do this:
select event_starttime + (1/1440*15) from event;
Converting to other data type is not possible
I can only use to_char and to_date to do it
Those two statements are contradictory. to_date() converts from a string data type to to a date data type; to_char() does the reverse.
But lets assume the second one is your actual requirement, and the assignment is not to use other functions like to_dsinterval() or other data types like intervals - however arbitrary a restriction that is.
If the starting date has its time set to midnight then you can convert just the date portion to a string, append the new time also still as a string, and convert the result to a date:
to_date(to_char(event_starttime, 'YYYY-MM-DD ') || '00:06:44', 'YYYY-MM-DD HH24:MI:SS')
Whether the starting date has its time as midnight or not, you can convert your time to a fraction of a day and add that; but that involves sysdate and trunc() as well as the two functions you mentioned:
event_starttime + (to_date('00:06:44', 'HH24:MI:SS') - trunc(sysdate, 'MM'))
That works because if you omit the date elements, to_date() gives you the specified time on the first day of the current month. And trunc(sysdate, 'MM') gives you midnight on that same day. Subtracting them gives you the fraction of a day that your time represents, which can then just be added to the original date, whatever time it already has.
db<>fiddle showing both, with the intermediate values so you can see what's happening.
Do not use TO_DATE and TO_CHAR as that is converting it to another data-type (TO_CHAR converts the date to a string and TO_DATE converts a string to a date). Instead, add an INTERVAL to the DATE which will result in another DATE value (and an unchanged data-type):
SELECT event_starttime + INTERVAL '00:06:44' HOUR TO SECOND
FROM event
WHERE event_id = ( SELECT event_id
FROM event
WHERE carn_date = SELECT TRUNC(carn_date)
FROM carnival
WHERE carn_name = 'RM Autumn Series Caulfield 2022'
)
AND eventtype_code = '21K'
)
If you do not see a difference then change the preferences for how SQL Developer displays dates using:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

Filtering a dataset by date and time Oracle SQL through Power BI

I'm having trouble with filtering a date and time for anything two hours before and sooner. I tried this:
SELECT *
FROM
table
where
date >= sysdate - 1
AND
TO_DATE( Time, 'HH24:MI:SS' ) >= TO_DATE( sysdate, 'HH24:MI:SS' ) - 2
But I'm getting an inconsistent type error which is what I thought I was handling with the TO_DATE() function but I guess not.
sysdate is already a date (and time), so TO_DATE( sysdate, 'HH24:MI:SS' ) doesn't make any sense.
You didn't provide your data types for your date and time columns in table, so I'm going to assume they're both varchar2(10) with formats MM/DD/YYYY and HH24:MI:SS respectively.
I'm also going to go ahead and change your example table and column names, since they're invalid names to use in a real query.
-- example data
with my_table as (select '06/13/2019' as date_column, '09:40:34' as time_column from dual)
-- your query
SELECT *
FROM
my_table
where
to_date(date_column || ' ' || time_column, 'MM/DD/YYYY HH24:MI:SS') >= sysdate - 2/24
What I'm doing here is to combine your date and time strings into one date-time string, then converting it to an Oracle date type (actually date+time). Then we compare it to sysdate - 2/24, which says to take the current time and subtract 2/24ths of a day, which is 2 hours.
For this example, you might need to change the example data date_column and time_column values to something from the past 2 hours, depending on when you run this and what time zone you're in.

SQL extracting hour and minute from date into a single column

I have a column in the format YYYY-MM-DDBHH:MI:SS and I wish to extract just the hour and minutes from this into a column. Currently on the code they are using
Extract(HOUR From table) AS HR
, Extract(MINUTE From table) AS MN
but this outputs them into 2 columns. I'm new to SQL so is there an easier way to extract hour and minutes into one column in the format HH:MI.
Thanks
Using Teradata, simply concatenate the output from each of the functions to give the answer:
Extract(HOUR From table) || ':' || Extract(MINUTE From table) AS OUTPUT
Don't know about teradata but something like this.
SELECT CONCAT(Extract(HOUR From table),Extract(MINUTE From table)) as HRandMI
If you got a Timestamp the easiest way to get a HH:MI string is:
to_char(mycol, 'HH24:MI')

How to trim or format the HH:MM:SS.ms value in Oracle SQL query

I have a query in Oracle SQL that displays results as follows:
SQL:
select
uuid, name,
to_char(from_tz(startdate, 'UTC') at time zone 'America/New_York', 'yyyy-mm-dd hh24:mi:ss') as startdate_et,
to_char(from_tz(enddate, 'UTC') at time zone 'America/New_York', 'yyyy-mm-dd hh24:mi:ss') as enddate_et,
(enddate - startdate) as executiontime
from
process
where
name = (select name from jobconfiguration where currentprocessid = 'bGd_AAABNaMAAAFQHvY0UyTa');
Output:
The problem here is the data in the executiontime column. The milliseconds value is too long and also I would like to remove the +00 from the beginning and trim the 02.951000 to 02.95 and 03.284000 to 03.28.
Please guide.
The difference between two timestamps is an interval. By default, this includes long fractions of the second.
For printing purposes, just use to_char():
to_char(fenddate - startdate, 'dd hh24:mi:ss') as executiontime
Because the default for the difference is an interval of "day to second", you only need to include these elements.
The difference of two timestamps is already well formatted and being printed in the format
+/-number of days hours:minutes:seconds.milliseconds
Why don't you want the +00, is it because it is 0 days?
I am assuming you would want it if the days difference is greater than zero?
Anyway it is easier to use substr to format the output as needed and use case when on number of days.
For example
substr(start_time-end_time, instr(start_time-end_time, '.')+1, 2) to trim milliseconds to two digits.
and
case when to_number(substr(start_time-end_time, 1, instr(start_time-end_time, ' '))) > 0 then substr(start_time-end_time, 1, instr(start_time-end_time, ' ')) else '' end
to get number of days
or substr(start_time-end_time, instr(start_time-end_time, ' ')) to remove the days completely

Compare date + time with timestamp

I have a table with two temporal columns. First (name is DATE) is storing the date (not including the time part) and therefor the datatype is DATE. Second column (name is TIME) is for storing the time in seconds and therefor the datatype is NUMBER.
I need to compare this two dates with a timestamp from another table. How can I calculate the date of the two columns (DATE and TIME) and compare to the timestamp of the other table?
I have tried to calculate the hours out of the time column and add it to the date column, but the output seems not correct:
SELECT to_date(date + (time/3600), 'dd-mm-yy hh24:mi:ss') FROM mytable;
The output is just the date, but not the time component.
You can use the INTERVAL DAY TO SECOND type:
SELECT your_date + NUMTODSINTERVAL(your_time_in_seconds, 'SECOND') FROM dual;
Example:
SELECT TRUNC(SYSDATE) + NUMTODSINTERVAL(39687, 'SECOND') FROM dual;
The calculated date with time is: 10-11-2013 11:01:27
This is a better idea than dividing your value by 3600 in my opinion, as you have an interval in seconds, so it feels natural to use an interval to represent your time, which can then be easily added to a column of DATE datatype.
Oracle Interval in Documentation
NUMTODSINTERVAL Function in documentation
date + (time/3600) is already a DATE, so you don't need to do to_date(). It does have the time part you added though, you just aren't displaying it. If you want to output that as a string in the format you've shown, use to_char() instead:
SELECT to_char(date + (time/3600), 'dd-mm-yy hh24:mi:ss') FROM mytable;
... except that if time is actually in seconds, you need to divide by 86400 (24x60x60), not 3600. At the moment you're relying on your client's default date format, probably NLS_DATE_FORMAT, which doesn't include the time portion from what you've said. That doesn't mean the time isn't there, it just isn't displayed.
But that is just for display. Leave it as a date, by just adding the two values, when comparing against you timestamp, e.g.
WHERE date + (time/86400) < systimestamp
Try like this,
SELECT TO_DATE('11/11/2013','dd/mm/yyyy') + 3600/60/60/24 FROM DUAL;
Your query,
SELECT date + time/60/60/24 FROM mytable;
try using to_timestamp instead of to_date