Fine tune EXTRACT HOUR and DAY - oracle

I have a logic as per below query to extract the number of days from timestamp and present in hours.
CASE WHEN LATEST_TIMESTAMP IS NULL
THEN
EXTRACT (HOUR FROM (SYSDATE - CREATION_TIMESTAMP)) + EXTRACT (DAY FROM (SYSDATE -
CREATION_TIMESTAMP)) * 24
ELSE
EXTRACT (HOUR FROM (LATEST_TIMESTAMP - CREATION_TIMESTAMP)) + EXTRACT (DAY FROM
(LATEST_TIMESTAMP - CREATION_TIMESTAMP)) * 24
END
AS TIME_IN_HOURS
It works inefficiently when deal with multiple records, anyway if can fine tune the query?

Difference of two DATE datatype values is a number of days between them. Therefore, if you "shorten" your code to use NVL (for cases where latest_timestamp is NULL) and simply multiply that result by 24 (to get number of hours), you'd get
select (nvl(latest_timestamp, sysdate) - creation_timestamp)) * 24 as time_in_hours
from some_table
That result should probably be rounded (but that's easy).
See if it helps.

Combined solution with NVL and Extract
select EXTRACT (DAY FROM(nvl(latest_timestamp, sysdate) - creation_timestamp)) * 24) as time_in_hours from some_table

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.

Trying to calculate difference between two date in format (00-00-0000 00:00:00 ) in minutes in oracle

I have date in following format a_time=01-06-2020 15:28:06 & b_time=01-06-2020 15:39:00 in table t_mst
and i want to convert diff of given values in queries in minutes
select (extract( day from diff )*24*60*60 +
extract( hour from diff )*60*60 +
extract( minute from diff )*60 +
extract( second from diff ))/60 total_Minutes
from(select b_time - a_time diff
from t_mst Where a_time between (trunc(sysdate, 'mm')) and (sysdate))
But getting Error "Invalid extract field for extract source"
any idea would be appreciated.
The error you show means that b_time - a_time worked. Which means they are in date (or perhaps timestamp) data type; that is good.
Then, they must be date; if they were timestamp then the difference would be interval data type, and you can indeed extract time elements from interval. So, the error message suggests that the data type of a_time and b_time is indeed date.
Now: In Oracle, the difference between two dates is a number (in days); you can't extract time elements from a number. Instead, consider that the difference is already a number of days (including a fractional part); to convert it to minutes, you only have to multiply it by 1440 - and then round the result, if needed.
You have tagged with 3 databases and the code is for postgreSQL. I assume you meant, postgreSQL:
select (extract( epoch from age(a_time, b_time)/60) total_Minutes
from t_mst
--Where a_time between (trunc(sysdate, 'mm')) and (sysdate))
If you need it casted to int:
select (extract( epoch from age(a_time, b_time)/60)::int total_Minutes
from t_mst
PS: Not sure you meant plSQL or PL\pgSQL.
If b_timeand a_time data types are DATE you can simply run
select (b_time - a_time) * 24*60 AS total_Minutes
from t_mst
Where a_time between trunc(sysdate, 'mm') and sysdate
In case they are TIMESTAMP data type you have to extract the values, e.g. like this:
select
EXTRACT(DAY FROM (b_time - a_time))*24*60
+ EXTRACT(HOUR FROM (b_time - a_time))*60
+ EXTRACT(MINUTE FROM (b_time - a_time))
+ EXTRACT(SECOND FROM (b_time - a_time))/60
AS total_Minutes
from t_mst
Where a_time between trunc(sysdate, 'mm') and sysdate

How to generate diff between TIMESTAMP and DATE in SELECT in oracle 10

I need to query 2 tables, one contains a TIMESTAMP(6) column, other contains a DATE column. I want to write a select statement that prints both values and diff between these two in third column.
SB_BATCH.B_CREATE_DT - timestamp
SB_MESSAGE.M_START_TIME - date
SELECT SB_BATCH.B_UID, SB_BATCH.B_CREATE_DT, SB_MESSAGE.M_START_TIME,
to_date(to_char(SB_BATCH.B_CREATE_DT), 'DD-MON-RR HH24:MI:SS') as time_in_minutes
FROM SB_BATCH, SB_MESSAGE
WHERE
SB_BATCH.B_UID = SB_MESSAGE.M_B_UID;
Result:
Error report -
SQL Error: ORA-01830: date format picture ends before converting entire input string
01830. 00000 - "date format picture ends before converting entire input string"
You can subtract two timestamps to get an INTERVAL DAY TO SECOND, from which you calculate how many minutes elapsed between the two timestamps. In order to convert SB_MESSAGE.M_START_TIME to a timestamp you can use CAST.
Note that I have also removed your implicit table join with an explicit INNER JOIN, moving the join condition to the ON clause.
SELECT t.B_UID,
t.B_CREATE_DT,
t.M_START_TIME,
EXTRACT(DAY FROM t.diff)*24*60 +
EXTRACT(HOUR FROM t.diff)*60 +
EXTRACT(MINUTE FROM t.diff) +
ROUND(EXTRACT(SECOND FROM t.diff) / 60.0) AS diff_in_minutes
FROM
(
SELECT SB_BATCH.B_UID,
SB_BATCH.B_CREATE_DT,
SB_MESSAGE.M_START_TIME,
SB_BATCH.B_CREATE_DT - CAST(SB_MESSAGE.M_START_TIME AS TIMESTAMP) AS diff
FROM SB_BATCH
INNER JOIN SB_MESSAGE
ON SB_BATCH.B_UID = SB_MESSAGE.M_B_UID
) t
Convert the timestamp to a date using cast(... as date). Then take the difference between the dates, which is a number - expressed in days, so if you want it in minutes, multiply by 24*60. Then round the result as needed. I made up a small example below to isolate just the steps needed to answer your question. (Note that your query has many other problems, for example you didn't actually take a difference of anything anywhere. If you need help with your query in general, please post it as a separate question.)
select ts, dt, round( (sysdate - cast(ts as date))*24*60, 2) as time_diff_in_minutes
from (select to_timestamp('2016-08-23 03:22:44.734000', 'yyyy-mm-dd hh24:mi:ss.ff') as ts,
sysdate as dt from dual )
;
TS DT TIME_DIFF_IN_MINUTES
-------------------------------- ------------------- --------------------
2016-08-23 03:22:44.734000000 2016-08-23 08:09:15 286.52

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: 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