SYSDATE but specify the time - sql

I want to say the follow but substitute the date with SYSDATE but the time between is what I want to adjust. What would the syntax be?
where mydatefield between SYSDATE+'0001' and SYSDATE+'2359'
...
WHERE TO_CHAR( MOPACTIVITY.MOPNOTIFICATIONSENDAT , 'yyyy-mm-dd hh24:mi' )
BETWEEN '2013-07-26 00:00:01' AND '2013-07-26 23:59:59'
;

SYSDATE (or any other date column) in Oracle has the time component. So you need to strip that off and then add the hours/minutes/time condition.
Eg. to say current day 10:00 AM to 3:00 PM, you can say
date_column between (trunc(sysdate) + 10/24) and (trunc(sysdate) + 15/24)
Oracle date arithmetic works on the day level. so, +1 will give you the next day, 1/24 will give you an hour and 10/24 will give you 10:00 AM in the current day.
SQL> alter session set nls_date_format = 'DD-Mon-YYYY HH:MI:SS AM';
Session altered.
1 select sysdate,
2 trunc(sysdate),
3 trunc(sysdate) + 10/24,
4 trunc(sysdate) + 15/24
5* from dual
SQL> /
SYSDATE 26-Jul-2013 06:26:07 PM
TRUNC(SYSDATE) 26-Jul-2013 12:00:00 AM
TRUNC(SYSDATE)+10/24 26-Jul-2013 10:00:00 AM
TRUNC(SYSDATE)+15/24 26-Jul-2013 03:00:00 PM
For your question, you seem to be interested between current day and next day, so you can try adding + 1 to the date directly, once you strip the time component.
date_column >= trunc(sysdate) and
date_column < trunc(sysdate)+1

The best way to do this is to leave your MOPACTIVITY.MOPNOTIFICATIONSENDAT as a DATE type. That allows Oracle to optimize the query if there happens to be an index on the column. I'd recommend something like this:
WHERE MOPACTIVITY.MOPNOTIFICATIONSENDAT >= TRUNC(SYSDATE)
AND MOPACTIVITY.MOPNOTIFICATIONSENDAT < TRUNC(SYSDATE) + 1
That boils down to "greater than or equal to today at midnight" and "less than tomorrow at midnight".

We can also trunc both the dates and then compare the result
where TRUNC(MOPACTIVITY.MOPNOTIFICATIONSENDAT) = TRUNC(SYSDATE)
TRUNC Removes the timestamp from the dates

Related

Get systime at a specific time and date - Oracle SQL

Is it possible to do something like this?
SELECT
TO_CHAR(SYSDATE-1, 'MM-DD-YYYY 08:00:00') "Yesterday",
I'd like to get the sysdate from yesterday at 8am
You would write this as:
trunc(sysdate - 1) + interval '8' hour
Or:
trunc(sysdate) - interval '16' hour
Or you can do date arithmetics with integer values rather than intervals:
trunc(sysdate) - 16/24
Truncate the sysdate. That will remove the time portion of the date.
Then add 8/24 (8 hours of the 24), 8/24 equals to 1/3 - 8 hours is a third of a day.
Then display this date value in the format DD-MON-YYYY HH24:MI:SS.
This all adds up to:
SELECT TO_CHAR(TRUNC(SYSDATE) - 1 + 1/3,'DD-MON-YYYY HH24:MI:SS') FROM DUAL;

ORACLE using TO_DATE to check if item is within last hour

I have a query that I am trying to use TO_DATE to check if ERROR_DT is a data that is within one hour of the current time
Here is what I have so far
SELECT BERROR_DT FROM SomeTable
WHERE ERROR_DT>=TO_CHAR(TO_DATE( SYSDATE, 'MM/DD/YYYY HH12:MI:SS AM') -1, 'fmMM/DDfm/YYYY HH12:MI:SS AM');
Error_DT has a value of (e.g.) 5/18/2020 6:45:15 PM
When I run this I get
ORA-01830: date format picture ends before converting entire input string
I followed the said link and it still is not working. How would I fix this so that I can still remove all 0s in front of the month and the date?
I would suggest converting the date string to the corresponding date value, then do the comparison:
select berror_dt
from sometable
where to_date(error_dt, 'fmMM/DD/YYYY HH12:MI:SS AM') >= sysdate - interval '1' hour
Bottom line, you should fix your data model and store dates as a date-like datatype rather than as a string. The above predicate is not efficient, because the conversion needs to be executed for each and every value of error_dt before the filtering applies, hence defeating an existing index on the column.
Obviously wrong thing you're doing is applying TO_DATE to SYSDATE which is a function that returns DATE datatype.
What you could do is to subtract sysdate and error_dt (I presume its datatype is DATE as well) and see whether difference is less than 1 hour. As difference of two dates is number of days, you have to divide it by 24 (as there are 24 hours in a day).
Something like this:
SQL> alter session set nls_date_format = ' dd.mm.yyyy hh:mi:ss am';
Session altered.
SQL> with test (id, error_dt) as
2 (select 1, to_date('18.05.2020 10:30:15 PM', 'dd.mm.yyyy hh:mi:ss am') from dual
3 union all
4 select 2, to_date('18.05.2020 05:20:55 AM', 'dd.mm.yyyy hh:mi:ss am') from dual)
5 select t.id, t.error_dt, sysdate
6 from test t
7 where sysdate - t.error_dt < 1 / 24;
ID ERROR_DT SYSDATE
---------- ----------------------- -----------------------
1 18.05.2020 10:30:15 PM 18.05.2020 11:02:24 PM
SQL>
If ERROR_DT is a DATE value you just need to use something like
SELECT BERROR_DT
FROM SomeTable
WHERE ERROR_DT >= SYSDATE - INTERVAL '1' HOUR
or if you prefer to use old-fashioned pre-INTERVAL calculations
SELECT BERROR_DT
FROM SomeTable
WHERE ERROR_DT >= SYSDATE - (1/24)

Select rows within last complete minute

I want to find rows in my database which have a timestamp within the last complete minute.
For example:
When it is 12:02:43 --> from 12:01:00 to 12:01:59 (inclusive)
When it is 14:01:00 --> from 14:00:00 to 14:00:59 (inclusive)
When it is 16:24:59 --> from 16:23:00 to 16:23:59 (inclusive)
I found the following statement.
select *
from table
where time < to_date(to_char(sysdate, 'DD.MM.YYYY HH24:MI'), 'DD.MM.YYYY HH24:MI')
and time >= to_date(to_char(sysdate - numtodsinterval(1, 'Minute'), 'DD.MM.YYYY HH24:MI'), 'DD.MM.YYYY HH24:MI')
The statement works, but converting the date to a string and then back to a date seems a little weird. Is there any other method to use only minutes as precision (without seconds)?
Oracle-specific functions could be used, but I'd prefer a standard SQL way.
You can use TRUNC(SYSDATE,'MI') -> TRUNC('12:02:43','MI') = 12:02.
Or you can use this select extract(MINUTE from current_timestamp) from dual;
You can truncate timestamps (and dates) to the nearest minute - so you can use TRUNC( SYSTIMESTAMP, 'MI' ) to round to the start of the current minute and subtract INTERVAL '1' MINUTE to get the start of the previous minute:
select *
from table_name
where time >= TRUNC( SYSTIMESTAMP, 'MI' ) - INTERVAL '1' MINUTE
and time < TRUNC( SYSTIMESTAMP, 'MI' )
You are right, converting it to string an back seems unnecessary. I'd leave it as a date. How about:
SELECT *
FROM t
WHERE t BETWEEN TRUNC(SYSDATE,'MI')
AND TRUNC(SYSDATE,'MI')+1/24/60/60*59;
TRUNC(...,'MI') chops of the seconds, for instance
SELECT trunc(sysdate,'MI'), TRUNC(SYSDATE,'MI')+1/24/60/60*59 from dual;
returns
2018-06-06 11:04:00 2018-06-06 11:04:59
EDIT: As David Faber pointed out, this works only if your column has the datatype DATE. For the datatype TIMESTAMP, you're better of with #MT0's solution.

Last date with time of the month

Need your help to conclude the query to fetch last date time of the sysdate month.
select to_char(last_day(sysdate),'DD-Mon-YYYY HH24:MI:SS') from dual
it gives last date as expected, but I need time as 23:59:00 which is not possible thru above query.
You could use TRUNC on next day i.e. SYSDATE + 1, and then subtract 60 seconds i.e. 60/86400 to get the desired output.
SQL> SELECT to_char((trunc(last_day(sysdate)) +1) - 60/86400,'DD-Mon-YYYY HH24:MI:SS') dt
2 FROM dual;
DT
--------------------
29-Feb-2016 23:59:00
SQL>
You could also use interval '1' minute or interval '60' second instead of 60/86400.
If you just want it for display for some reason you can hard-code the time into the format mask:
select to_char(last_day(sysdate), 'DD-Mon-YYYY "23:59:00"') from dual;
But you probably really want it as a date object, in which case you can add 23 hours and 59 minutes to the truncated (midnight) date, wchi is 1439 of the 1440 minutes in a day:
select to_char(trunc(last_day(sysdate)) + 1439/1440, 'DD-Mon-YYYY HH24:MI:SS')
from dual;
Or you can go to the next day and remove a minute, either with fractional days or with intervals:
select to_char(trunc(last_day(sysdate)) + interval '1' day - interval '1' minute,
'DD-Mon-YYYY HH24:MI:SS') from dual;
Generally if you're working with time periods you want to include up to 23:59:59, which you can also do with any of those methods, but as Damien_The_Unbeliever said in a comment, it's easier to compare against the start of the next period (e.g. < add_months(trunc(sysdate, 'MM'), 1). It's easy to accidentally miss part of a day by not taking the time into account properly, particularly if you actually have a timestamp rather than a date.

Sysdate vs Timestamp for comparisons

I'm checking for product updates that are dependent on time of day - alerting if a product has not updated in the last 2 hours , e.g.:
03:30 - 07:29 we expect only product x to be updating;
07:30 - 11:29 we expect both product x and y to be updating
11:30 - 15:30 we expect only product y to be updating
But we need to be sensitive to products that have not updated yesterday and still have not updated today. Thus my question - when doing the below timestamp comparisons for product y, I suspect that date is not factored in and therefore a product that hadn't updated potentially gets ignored.
(...)
AND inv.timestamp < sysdate - (120 / 1440) --older than two hours
AND inv.timestamp > TRUNC(sysdate) + (690/1440) --after 11:30
AND inv.timestamp < TRUNC(sysdate) + (930/1440) --before 15:30
(...)
inv.timestamp is a column in timestamp(6) type. Does trunc(sysdate) implicitly include the present date for comparison or is it only using the time?
TRUNC(SYSDATE) returns 00:00:00 of the current day.
SQL> select trunc(sysdate) from dual;
TRUNC(SYSDATE)
-------------------
2012-03-09 00:00:00
Documentation on TRUNC
As eaolson and Ben have already noted, SYSDATE includes the date AND time. Using TRUNC "removes" the time element, i.e. resets it to midnight of that day.
You may want to consider using the INTERVAL functionality provided by Oracle, to make it clearer what the SQL is doing, e.g.
SELECT to_char(trunc(sysdate) + interval '11' hour + interval '30' minute,'dd/mm/yyyy hh24:mi:ss') sysdate_trunced_to_1130,
to_char(trunc(current_timestamp) + interval '11' hour + interval '30' minute,'dd/mm/yyyy hh24:mi:ss') timestamp_trunced_to_1130
FROM dual;
Glancing at the code, "(690/1440)" doesn't immediately suggest 11:30 in the morning, but + interval '11' hour + interval '30' minute hopefully is a little better.