Add minutes to an Oracle date - sql

I am trying to add minutes to my sql but no error and no data.
This is my sql
select distinct mo.reference_no payment_id, mo.dcn message_id,
mo.amount, mo.ccy, decode (mo.msg_status, 'R', 'Repair', 'P',
'Processed','N','Ungenerated','G','Generated',mo.msg_status)
message_status, to_char
(MO.INSERT_TIME,'DD-MM-YYYY HH24:MI:SS')
paym_date, mo.branch_date, mo.maker_id
from table1 mo
left join table2 mi
on mo.reference_no = mi.generated_ref_no
where mo.swift_msg_type = 103
and mo.ccy = 'XXX' and mo.branch_date = trunc(sysdate)
and mo.msg_status in('R','N','G','P')
order by PAYM_DATE desc;
And I want to add 5 minutes to (MO.INSERT_TIME,'DD-MM-YYYY HH24:MI:SS')
So I want my sql show me after 5 minutes for this column (MO.INSERT_TIME,'DD-MM-YYYY HH24:MI:SS')
I wrote sql like that
select distinct mo.reference_no payment_id, mo.dcn message_id,
mo.amount, mo.ccy, decode (mo.msg_status, 'R', 'Repair', 'P',
'Processed','N','Ungenerated','G','Generated',mo.msg_status)
message_status, to_char
(MO.INSERT_TIME,'DD-MM-YYYY HH24:MI:SS')
paym_date, mo.branch_date, mo.maker_id
from table1 mo
left join table2 mi
on mo.reference_no = mi.generated_ref_no
where mo.swift_msg_type = 103
and mo.ccy = 'XXX' and mo.branch_date = trunc(sysdate)
and MO.INSERT_TIME = to_date (sysdate,'DD-MM-YYYY HH24:MI:SS') + INTERVAL '5' MINUTE
and mo.msg_status in('R','N','G','P')
order by PAYM_DATE desc;
And after 5 minutes I am selecting this sql and their is no data. Can you explain why?

This is what you used:
and MO.INSERT_TIME = to_date (sysdate,'DD-MM-YYYY HH24:MI:SS') + INTERVAL '5' MINUTE
It is wrong because you're applying TO_DATE function to SYSDATE which already returns DATE datatype, so there's no point in doing it.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate,
2 sysdate + interval '5' minute
3 from dual;
SYSDATE SYSDATE+INTERVAL'5'
------------------- -------------------
10.01.2023 09:49:05 10.01.2023 09:54:05
SQL>
It is probably not very likely that MO.INSERT_TIME will exactly be the same as SYSDATE (which is right now) + 5 minutes, which is in the future.
Perhaps you'd rather set that condition to e.g. rows inserted during last 5 minutes (which makes more sense to me):
and MO.INSERT_TIME >= sysdate - INTERVAL '5' MINUTE

DATE + NUMBER where number can be fractional and is interpreted as days, and a minute is 1/(24*60) of a day...

Related

Column based on time range in Oracle

I have a sales table with created datetime, my business hours are from 9 AM to 2 AM in the night on the following day. I am trying to convert the dates into my business date.
01/08/22 09:39:12.000000000 AM +04:00
Lets say I have a sale at 1 AM, this sale has to be considered in the previous day.
Any function that can help me solve this issue would be appreciated
It might be a bit of an overkill, but you could just use EXTRACT:
WITH dat AS
(
SELECT to_date('01/08/22 09:39:12','DD/MM/YY HH24:MI:SS') AS t_stmp FROM dual UNION ALL
SELECT to_date('02/08/22 01:03:15','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 08:27:33','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 14:11:51','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 02:01:15','DD/MM/YY HH24:MI:SS') FROM dual
)
SELECT CASE WHEN EXTRACT(HOUR FROM CAST(t_stmp AS TIMESTAMP)) BETWEEN 2 AND 8 THEN -1
ELSE 0
END + TRUNC(t_stmp,'DD') AS business_date
FROM dat;
business_date
01.08.2022
02.08.2022
01.08.2022
02.08.2022
01.08.2022
It looks like you just need to make a 2 hour shift to get your sales in the right date. You can add or substract hours from DATE/DATETIME/TIMESTAMP data type. If your column is TIMESTAMP then it would be like this:
-- when selecting data for date of sales
SELECT TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') "SALE_DATE"
-- And/Or
WHERE TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') = :DATE_OF_SALES
-- TRUNC function always returns DATE datatype
--
-- The opposite conversion would be
CAST(your_datetime_column + INTERVAL '2' HOUR as TIMESTAMP) ...
Here is the small sample with result:
SELECT
to_char(SYSDATE, 'dd.mm.yyyy hh24:mi:ss') "DATETIME",
to_char(SYSDATE - INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_2H",
to_char(SYSDATE + INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_PLUS_2H",
to_char(SYSDATE - INTERVAL '10' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_10H"
FROM
DUAL
--
-- R e s u l t
--
-- DATETIME DATETIME_MINUS_2H DATETIME_PLUS_2H DATETIME_MINUS_10H
-- ------------------- ------------------- ------------------- -------------------
-- 07.08.2022 09:58:38 07.08.2022 07:58:38 07.08.2022 11:58:38 06.08.2022 23:58:38
The last column now has the date from day before.

SQL - How to print calculated datetime result

[user#hostname ~]$ sqlplus -v
SQL*Plus: Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
select
a.user_id as user_id,
/* convert to minutes */
(to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss') - to_date(b.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')) 60 * 24 as minutes
from
(select user_id, modified_datetime, from table_name where some_conditions) a,
(select user_id, modified_datetime, from table_name where other_conditions) b,
where a.user_id = b.user_id
;
If a.modified_datetime is '2021/10/01 13:00:00' and b.modified_datetime is '2021/10/01 12:30:00', the result of this query would be:
user_id minutes
------- -------
12345 30
However, I run this query via sqlplus, it returns
user_id minutes
------- -------
12345 0
What's wrong with this query, or need to set some options to sqlplus?
it is stored in a date column
As #a_horse_with_no_name pointed out in a comment, calling to_date() on a value that is already a date is incorrect, and is causing your apparent problem.
When you do:
to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')
you are implicitly converting the date to a string using the current session NLS settings; with the still-default DD-MON-RR for example, that is really doing:
to_date(a.modified_datetime, 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime), 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime, <NLS_DATE_FORMAT>), 'yyyy/mm/dd hh24:mi:ss')
-> to_date(to_char(a.modified_datetime, 'DD-MON-RR'), 'yyyy/mm/dd hh24:mi:ss')
-> to_date('01-OCT-21', 'yyyy/mm/dd hh24:mi:ss')
-> 0001-10-21 00:00:00
As both values end up as midnight, the difference between them is calculated as zero minutes.
You could change the NLS settings, which is fragile; or explicitly convert the the date to a string in the right format - but neither is necessary or useful.
You should not have the to_date() calls at all, and can just subtract the date values directly from each other:
select
a.user_id as user_id,
(a.modified_datetime - b.modified_datetime) * 60 * 24 as minutes
from
(select user_id, modified_datetime from table_name where some_conditions) a,
(select user_id, modified_datetime from table_name where other_conditions) b
where a.user_id = b.user_id;
or using ANSI joins:
select
a.user_id as user_id,
(a.modified_datetime - b.modified_datetime) * 60 * 24 as minutes
from
(select user_id, modified_datetime from table_name where some_conditions) a
join
(select user_id, modified_datetime from table_name where other_conditions) b
on a.user_id = b.user_id;
db<>fiddle showing the results of the implicit conversions, and the correct output.
It is 30 minutes, if values really are as you stated:
SQL> with test (a_time, b_time) as
2 (select to_date('2021/10/01 13:00:00', 'yyyy/mm/dd hh24:mi:ss'),
3 to_date('2021/10/01 12:30:00', 'yyyy/mm/dd hh24:mi:ss')
4 from dual
5 )
6 select (a_time - b_time) * 60 * 24 as minutes
7 from test;
MINUTES
----------
30
SQL>

How to return a date field to add two days and not affect the original date?

We have a column that holds a date (MM/DD/YYYY) that someone's account was last updated by an automated service. When this date is two days old we have another automated service that automatically sets a hold on an account.
Basically I need to return the date that the hold was actually placed on the account. The following is my code to return all users who have this placed. e.lastupdate is the field that needs two days added to it
select p.id||' '||p.lastname||' '||p.firstname||' '|| e.lastupdate
from table p, othertable e
where p.id = e.id
and hold = 8
and id in (
select id from othertable
where buildinginfo is null
)
order by id;
Expected results to be two days after the "e.lastupdate" field
I'm not sure if the answer you are seeking is simply a question regarding how to work with dates? If so see my answer which shows how to perform calculations on dates/times.
The below simply has a new column added to your query called lastupdate_plus_2_days
SELECT p.id||' '||p.lastname||' '||p.firstname||' '|| e.lastupdate + 2
, e.lastupdate + 2 AS lastupdate_plus_2_days
FROM some_TABLE p, othertable e
WHERE p.id = e.id
AND hold = 8
AND id IN
(
SELECT id
FROM othertable
WHERE buildinginfo IS NULL
)
ORDER BY id;
Examples Working with Dates
/* Working with SYSDATE and to_char formats */
SELECT
sysdate -365 Last_Year,
to_char(to_date('04-DEC-2013', 'DD-MON-YY') - 365, 'DD-MON-YYYY') AS Last_Year2,
add_months(sysdate, -1) Last_Month,
sysdate -7 Last_Week,
sysdate -1 Yesterday,
sysdate Today,
to_char(sysdate, 'DD-MON-YY HH:MI:SS') NOW,
to_char(sysdate + 1/(24*60*60), 'DD-MON-YY HH:MI:SS') "OneSecFrom_NOW",
to_char(sysdate + 2/(24*60*60), 'DD-MON-YY HH:MI:SS') "TwoSecFrom_NOW",
to_char(sysdate + 1/(24*60), 'DD-MON-YY HH:MI:SS') "OneMinFrom_NOW",
to_char(sysdate + 7/(24*60), 'DD-MON-YY HH:MI:SS') "SevMinFrom_NOW",
to_char(sysdate + 1/24, 'DD-MON-YY HH:MI:SS') "OneHrFrom_NOW",
sysdate +1 Tomorrow,
sysdate +7 Next_Week,
last_day(sysdate) as last_day_of_month,
add_months(sysdate, 1) Next_Month,
last_day(add_months(sysdate, 1)) as last_day_of_next_month,
sysdate +365 Next_Year,
/* Below are examples of how you could disect a number of days and spit out how many years, months, days are within those days using the mod function. */
trunc((to_date('02-FEB-14') - to_date('01-JAN-13'))/365) "~yr", trunc(mod((to_date('02-FEB-14') - to_date('01-JAN-13')),365)/31) "~mon", mod(mod((to_date('02-FEB-14') - to_date('01-JAN-13')),365),31) "~days"
FROM
dual;
Is this answer at all what you were looking for? Unless there is code somewhere performing an 'UPDATE' the original date coming back from your 'SELECT' query will never change the original date value in the table from which you are pulling the data.

How to subtract Sys with Timestamp from field and get hours and minutes

This is my current query
SELECT
TABLE1.OUT_NO,
To_char(sysdate, 'MM-DD-YYYY HH24:MI:SS') as "Current_Time",
To_char(TABLE2.time_stamp, 'MM-DD-YYYY HH24:MI:SS') as "Recorded_Time"
FROM TABLE1 TABLE1 LEFT OUTER JOIN TABLE2 TABLE2 ON TABLE1.OUT_NO = TABLE2.OUT_NO
WHERE TABLE1.OUT_NO > '12345'
I need to subtract Current_time - Recorded_Time and get result in Hours and Minutes.
how can I achieve this?
Simply subtract one from the other
select sysdate - systimestamp from dual;
Ensure that they're still a DATE and a TIMESTAMP, do not convert them to characters first. This returns an INTERVAL datatype.
Apparently this is giving you an integer, which means your timestamp is being implicitly converted to a date (or is in fact already a date and not a timestamp).
If this is the case you have the number of days between the two dates; multiply by the number of minutes in a day in order to get this in minutes:
select ( sysdate - systimestamp ) * 60 * 24 from dual;
use datediff() built-in function
SELECT
TABLE1.OUT_NO,
To_char(sysdate, 'MM-DD-YYYY HH24:MI:SS') as "Current_Time",
To_char(TABLE2.time_stamp, 'MM-DD-YYYY HH24:MI:SS') as "Recorded_Time",
datediff(mi,time_stamp,getdate()) as DiffInTime
FROM TABLE1 TABLE1 LEFT OUTER JOIN TABLE2 TABLE2 ON TABLE1.OUT_NO = TABLE2.OUT_NO
WHERE TABLE1.OUT_NO > '12345'
will show results in minutes. Dance from there.

Oracle Set operator query

Have a SQL query on Oracle 11g which returns the count of whether a record having certain ID and status exists within +/- 15 minutes range in a table.
Now I wish to ignore the current date by adding a condition like AND TIMESTAMP < trunc(sysdate).
However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
How do I do this?
The first problem with your query is that you're doing a string comparison on the date. Use to_date instead of to_char and let Oracle help you out.
SELECT
to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') AS orig_date
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') - 1 / 24 / 4 AS fifteen_min_prior
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') + 1 / 24 / 4 AS fifteen_min_after
FROM dual;
Output:
ORIG_DATE FIFTEEN_MIN_PRIOR FIFTEEN_MIN_AFTER
------------------------- ------------------------- -------------------------
20-JUL-10 07:15:11 PM 20-JUL-10 07:00:11 PM 20-JUL-10 07:30:11 PM
Then use can use those dates in a BETWEEN condition in the predicate. See Oracle date "Between" Query.
I'm not quite clear what you mean by "However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query." You'd just written that you want to exclude values from the current day. Either you're excluding today's records or you're not.
Ok, you can try something like this, if I understood you correctly:
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
In this Select, you only apply the 15 minutes condition if your timestamp column has a date prior to sysdate.