Apply average( ) function to datediff between timestamp fields - oracle

I have some data that looks like this:
my_table
name
start
end
Michigan
06-NOV-20 08.25.59.000000000 AM
06-NOV-20 08.44.52.000000000 AM
State
22-NOV-20 11.49.11.000000000 AM
22-NOV-20 11.54.06.000000000 AM
I'm trying to create a new column to calculate the duration as the difference between start and end. I then want to apply a mathematical average (mean/median) to find the average duration by year.
My code, currently:
SELECT
start - end AS duration
FROM
my_table
Current output:
duration
-0 0:18:53.0
-0 0:4:55.0
What I want:
duration
1133
295
How can I go about converting the duration field from datetime to seconds or minutes, so that I can apply an average function to the duration field?

I suggest you spend some time with the Oracle Documentation for your version, also for a fairly quick overview of date/timestamp see here (not just the first sub-topic).
Your issue is what is the results of date/timestamp subtraction. There are two results you can get. Subtracting dates results in a floating point number where the whole number part represents days, and the decimal part the fraction of a day. Subtracting timestamps results in an data type Interval Day to Second. This case deals with timestamps. The Extract is used to get the individual components of the interval. Since you are after the duration in seconds you extract each component multiplying by the appropriate value to convert to seconds, and total the results:
select extract(day from diff) * 60 * 60 * 24 -- days to seconds
+ extract(hour from diff) * 60 * 60 -- hours to seconds
+ extract(minute from diff) * 60 -- minutes to seconds
+ extract(second from diff) -- seconds
from (
select to_timestamp('06-NOV-20 08.44.52.000000000 AM', 'dd-mon-yy hh12.mi.ss.ff AM')
- to_timestamp('06-NOV-20 08.25.59.000000000 AM', 'dd-mon-yy hh12.mi.ss.ff AM') diff
from dual
);

I found this online. Will this help?
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:10729709873260

Related

Oracle Time Range Query

I need to write a query which will do a date lookup by the most completed quarter hour.
So, if the current time is 5:35, then the criteria would be 5:15 - 5:30. If the time is 5:46, then 5:30 - 5:45, if the time is 6:02, then 5:45 - 6:00.
Not sure how to easily do this.
Something like
with cqh (dt) as (
select trunc(sysdate, 'hh') +
trunc(extract(minute from systimestamp) / 15) * interval '15' minute
from dual
)
select [_data_] from [_your_table_] cross join cqh
where [_date_column_] >= cqh.dt - interval '15' minute
and [_date_column_] < cqh.dt
;
The subquery calculates the most recently completed quarter-hour. It first truncates SYSDATE to the beginning of the current hour. Then we add a multiple of 15 minutes - the multiplier is 0, 1, 2 or 3, depending on the minute component of SYSDATE. Alas, EXTRACT(MINUTE FROM ...) only works on timestamps, so I had to use SYSTIMESTAMP there instead of SYSDATE, but other than that, the computation should be pretty obvious.
Then cross-join whatever else gives you "the data" to this small helper view, to use the DT value calculated in it.

logic to define arrival time greater than 30 minutes of scheduled appointment window end time : Oracle

Oracle SQL developer:
I have 2 fields in question -
Arrival time : Date time format (example: 01-JAN-15 11:03:00)
Service window End time: HH:MM (Varchar) ( example: 20:00)
I have to apply the logic where Arrival time is 30 minutes or more after service window end time.
Thank you very much for the help in advance.
Considering your arrival_time as date, we can use following logic.
Select * from your_table
Where (to_date(
to_char(arrival_time,'dd-mon-yyyy')
|| ' '
||service_window_end_time
,'dd-mon-yyyy hh24:mi') - arrival_time)*24*60 > 30
-- difference of dates give the number of days
-- so converted it to number of minutes by multiplying it with 24*60
But please note that your logic will not work when arrival_time and service_window_end_time represents different days.
Cheers!!
You will want to use INTERVAL to add minutes.
SELECT SYSDATE schedule_end_time,
SYSDATE + INTERVAL '30' MINUTE arrival_time
FROM dual
You can then use this in the WHERE clause with a greater than operator to do the comparison.

Oracle current_timestamp to second including milliseconds

This is my first time posting here. I've been looking out for all threads here & other websites but still I'm unable to fix the codes.
Here it is, I have a sample table called LM Where the structure looks like this: (Cannot change table structure)
LM_REFID(PK) LM_DESC
----------------------------------
VARCHAR2(50) VARCHAR2(50)
And LM_REFID is the PRIMARY KEY
So, here the things, I want to create a BEFORE INSERT trigger to assign timestamp values in seconds, including the milliseconds. It has to be counted in seconds (with milliseconds) from current time to 1/1/1970 00:00:00 (db time)
(As considering the simultaneous insert would violates PK due to same seconds values. Hence, I want the milliseconds values so the PK is unique)
The trigger looks like this:
CREATE OR REPLACE TRIGGER LM_TRG
BEFORE INSERT ON LM
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
:new.LM_REFID := (SYSDATE - TO_DATE('01/01/1970 00:00:00','MM-DD-YYYY HH24:MI:SS'))
* 24 * 60 * 60 ;
END;
/
This would result to values returned in SECONDS is 1449677554
But I don't want the SECONDS only, I want the milliseconds too, so the PK is unique. So, I've tried replaced the SYSDATE function with timestamp there like:
:new.LM_REFID:= (CURRENT_TIMESTAMP - TO_TIMESTAMP ('01/01/1970 00:00:00',
'MM-DD-YYYY HH24:MI:SSFF3')) * 24 * 60 * 60 * 1000
But it leads to error. I also have tried others like CAST, EXTRACT, epoch and more, but still no luck.
I want the sample data for example should be looked like this :
LM_REFID
----------------------------
1449677554.123456
1449677554.123344
1444677554.124466
Anyone can help to improve the trigger?
Thank you.
Maybe something like this:
declare
l_interval interval day(9) to second(6);
l_seconds number(24,6);
begin
l_interval := current_timestamp - timestamp '1970-01-01 00:00:00.000000';
l_seconds := extract(day from l_interval) * 24 * 60 * 60 +
extract(hour from l_interval) * 60 * 60 +
extract(minute from l_interval) * 60 +
extract(second from l_interval);
dbms_output.put_line(l_seconds);
end;
/
l_seconds will contain fractional seconds as well, that's why it has to be declared as number with decimal digits.
But I never get more than three decimal digits out of this - don't know why.

Oracle sqlSubtract between two date

I need help to write query do the following:
subtract between two columns (start date and end date), and please note that the type for the columns are char not date, this is the exact format: 10-MAR-12 11.11.40.288389000 AM), then get the average for the result.
I assume this is homework, so some hints...
First don't ever store dates as varchar, it will cause you and the optimiser all sorts of problems.
Second, Oracle's date datatype can only store to second precision, and your string has fractions of a second, so you are looking at timestamp rather than date. You can convert your string to a timestamp with the to_timestamp() function, passing a suitable format mask. Oh OK, I'm feeling generous:
select to_timestamp(start_date, 'DD-Mon-RR HH.MI.SS.FF9 AM') from your_table;
Third, subtracting two timestamps will give you an interval data type, from which you will need to extract the information you want in a readable format. Search this site or elsewhere for timestamp subtraction, but I'll point you at this recent one as a sample.
The average is a bit trickier, so you may want to convert your intervals to numbers for that; again search for previous questions, such as this one. The size of the intervals, the precision you actually care about, and the way you want the output formatted, etc. will have some bearing on the approach you want to take.
If you need an approximate result then #Joachim Isaksson's answer will give you that - 'approximate' because of rounding; a duration of less than a second will show up as zero, for example. The same effect can be seen with timestamps cast to dates, which also loses the fractional seconds:
select 24*60*60*avg(
cast(to_timestamp(step_ending_time, 'DD-Mon-RR HH.MI.SS.FF9 AM') as date)
- cast(to_timestamp(step_starting_time, 'DD-Mon-RR HH.MI.SS.FF9 AM') as date)
) as avg_duration
from process_audit;
A more accurate answer can be found by extracting the various components of the timestamps, as in a question I linked to earlier. You may not need them all if you know that your durations are always less then an hour, say, but if you need more than one (i.e. if a duration could be more than a minute) then using an intermediate common table expression simplifies things a bit:
with cte as (
select to_timestamp(step_ending_time, 'DD-Mon-RR HH.MI.SS.FF9 AM')
- to_timestamp(step_starting_time, 'DD-Mon-RR HH.MI.SS.FF9 AM') as duration
from process_audit
)
select avg(extract(second from duration)
+ extract(minute from duration) * 60
+ extract(hour from duration) * 60 * 60
+ extract(day from duration) * 60 * 60 * 24) as avg_duration
from cte;
With two sample rows, one with a gap of exactly a second and one with exactly 1.5 seconds, this gives the result 1.25.
Comments about storing times in VARCHAR aside; Oracle's to_date to the rescue; this should work for you to show the average number of seconds between the times. Since you're a bit low on details on precision, I didn't bother about the "sub seconds";
SELECT 24*3600*AVG(
to_date(enddate, 'DD-Mon-YY HH.Mi.SS.????????? AM') -
to_date(startdate, 'DD-Mon-YY HH.Mi.SS.????????? AM')) avg_seconds
FROM TableA;
Demo here.

Oracle: how to add minutes to a timestamp?

I need to add 30 minutes to values in a Oracle date column. I do this in my SELECT statement by specifying
to_char(date_and_time + (.000694 * 31)
which works fine most of the time. But not when the time is on the AM/PM border. For example, adding 30 minutes to 12:30 [which is PM] returns 1:00 which is AM. The answer I expect is 13:00. What's the correct way to do this?
In addition to being able to add a number of days to a date, you can use interval data types assuming you are on Oracle 9i or later, which can be somewhat easier to read,
SQL> ed
Wrote file afiedt.buf
SELECT sysdate, sysdate + interval '30' minute FROM dual
SQL> /
SYSDATE SYSDATE+INTERVAL'30'
-------------------- --------------------
02-NOV-2008 16:21:40 02-NOV-2008 16:51:40
All of the other answers are basically right but I don't think anyone's directly answered your original question.
Assuming that "date_and_time" in your example is a column with type DATE or TIMESTAMP, I think you just need to change this:
to_char(date_and_time + (.000694 * 31))
to this:
to_char(date_and_time + (.000694 * 31), 'DD-MON-YYYY HH24:MI')
It sounds like your default date format uses the "HH" code for the hour, not "HH24".
Also, I think your constant term is both confusing and imprecise. I guess what you did is calculate that (.000694) is about the value of a minute, and you are multiplying it by the number of minutes you want to add (31 in the example, although you said 30 in the text).
I would also start with a day and divide it into the units you want within your code. In this case, (1/48) would be 30 minutes; or if you wanted to break it up for clarity, you could write ( (1/24) * (1/2) ).
This would avoid rounding errors (except for those inherent in floating point which should be meaningless here) and is clearer, at least to me.
UPDATE "TABLE"
SET DATE_FIELD = CURRENT_TIMESTAMP + interval '48' minute
WHERE (...)
Where interval is one of
YEAR
MONTH
DAY
HOUR
MINUTE
SECOND
from http://www.orafaq.com/faq/how_does_one_add_a_day_hour_minute_second_to_a_date_value
The SYSDATE pseudo-column shows the current system date and time. Adding 1 to SYSDATE will advance the date by 1 day. Use fractions to add hours, minutes or seconds to the date
SQL> select sysdate, sysdate+1/24, sysdate +1/1440, sysdate + 1/86400 from dual;
SYSDATE SYSDATE+1/24 SYSDATE+1/1440 SYSDATE+1/86400
-------------------- -------------------- -------------------- --------------------
03-Jul-2002 08:32:12 03-Jul-2002 09:32:12 03-Jul-2002 08:33:12 03-Jul-2002 08:32:13
I prefer using an interval literal for this, because interval '30' minute or interval '5' second is a lot easier to read then 30 / (24 * 60) or 5 / (24 * 60 * 69)
e.g.
some_date + interval '2' hour
some_date + interval '30' minute
some_date + interval '5' second
some_date + interval '2' day
You can also combine several units into one expression:
some_date + interval '2 3:06' day to minute
Adds 2 days, 3 hours and 6 minutes to the date value
The above is also standard SQL and also works in several other DBMS.
More details in the manual: https://docs.oracle.com/database/121/SQLRF/sql_elements003.htm#SQLRF00221
If the data type of the field is date or timestamp, Oracle should always give the correct result if you add the correct number given in number of days (or a the correct fraction of a day in your case). So if you are trying to bump the value in 30 minutes, you should use :
select field + 0.5/24 from table;
Based on the information you provided, I believe this is what you tried to do and I am quite sure it works.
Can we not use this
SELECT date_and_time + INTERVAL '20:00' MINUTE TO SECOND FROM dual;
I am new to this domain.
like that very easily
i added 10 minutes to system date and always in preference use the Db server functions not custom one .
select to_char(sysdate + NUMTODSINTERVAL(10,'MINUTE'),'DD/MM/YYYY HH24:MI:SS') from dual;
Be sure that Oracle understands that the starting time is PM, and to specify the HH24 format mask for the final output.
SELECT to_char((to_date('12:40 PM', 'HH:MI AM') + (1/24/60) * 30), 'HH24:MI') as time
FROM dual
TIME
---------
13:10
Note: the 'AM' in the HH:MI is just the placeholder for the AM/PM meridian indicator. Could be also 'PM'
Oracle now has new built in functions to do this:
select systimestamp START_TIME, systimestamp + NUMTODSINTERVAL(30, 'minute') end_time from dual
Based on what you're asking for, you want the HH24:MI format for to_char.
To edit Date in oracle you can try
select to_char(<columnName> + 5 / 24 + 30 / (24 * 60),
'DD/MM/RRRR hh:mi AM') AS <logicalName> from <tableName>
SELECT to_char(sysdate + (1/24/60) * 30, 'dd/mm/yy HH24:MI am') from dual;
simply you can use this with various date format....

Resources