Oracle SQL What does start_date-1 mean? - sql

Oracle SQL What does start_date-1 mean?
Is it just one day less the start_date?

Assuming your datatype is a date or timestamp, yes, it will remove a full day from your date:
SELECT SYSDATE AS "start_date",
SYSDATE - 1 AS "start_date -1"
FROM DUAL;
Returns
26/08/2015 11:09:21 | 25/08/2015 11:09:21

YES. It will subrtract 1 day from the start_date.

Given that the data type of start_date is DATE or TIMESTAMP, subtracting N from it would subtract N number of days.
For example,
SQL> alter session set nls_date_format='DD-MM-YYYY HH24:MI:SS';
Session altered.
SQL> SELECT sysdate, sysdate -1 FROM DUAL;
SYSDATE SYSDATE-1
------------------- -------------------
26-08-2015 14:45:35 25-08-2015 14:45:35
SQL>
Remember, date has both date and time elements, so you will go back to previous day with exactly that time portion.

Yes it is 1 day earlier to start_date.

Related

How in Oracle to calculate difference between current date and column date?

I have column INACTIVE_TIME where I need to put integer number (how many days pass from some date), to represent difference between current date and column date ("LOAD_DATE" column).
In column LOAD_DATE I have data in format 03-AUG-22 03.55.57.587481000 PM.
I understand I need to get current date and than minus date from LOAD_DATE column.
I try something like this:
SELECT COUNT(*)
FROM TABLE_NAME
WHERE ((TO_DATE(SYSDATE,'DD/MM/YYYY')-(TO_DATE(LOAD_DATE,'DD/MM/YYYY'));
It is about load_date column's datatype, not the way you see that value (because it can be changed). I presume (and hope) it is timestamp; you aren't storing it as a string, are you?
If so, then you don't apply to_date to sysdate - it is a function that already returns date datatype.
Setting timestamp and date format (just to know what is what; your tool displays different format, with month name and two-digits year) (you don't have to do that).
SQL> alter session set nls_timestamp_format = 'dd.mm.yyyy hh24:mi:ss.ff9';
Session altered.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
Sample table; note datatype:
SQL> create table table_name (load_date timestamp);
Table created.
SQL> insert into table_name values (systimestamp);
1 row created.
Query you're looking for (at least, I think so):
SQL> select load_date, sysdate,
2 --
3 sysdate - load_date as diff
4 from table_name;
LOAD_DATE SYSDATE DIFF
------------------------------ ------------------- ------------------------------
04.08.2022 10:22:58.101062000 04.08.2022 10:23:08 +000000000 00:00:09.898938
SQL>
To extract days, hours, minutes ... whatever, you can use that function - extract. For example:
SQL> select load_date,
2 sysdate,
3 sysdate - load_date as diff,
4 --
5 extract (day from sysdate - load_date) as diff_days,
6 extract (hour from sysdate - load_date) as diff_hours,
7 extract (minute from sysdate - load_date) as diff_minutes
8 from table_name;
LOAD_DATE SYSDATE DIFF DIFF_DAYS DIFF_HOURS DIFF_MINUTES
------------------------- ------------------- -------------------------- ---------- ---------- ------------
04.08.22 10:22:58,101062 04.08.2022 11:51:32 +000000000 01:28:33.898938 0 1 28
SQL>
Your Where clause isn't saying anything. What are you wanting it to filter?
Try
Where (sysdate - table_name.load_date) > 0
This might not be what you want, but you need to tell the query something else

How to get 24 hours back time from current time in Oracle

I have a column in my Oracle db which records the creation time of a user in the following format
30-NOV-20 11.49.11.000000000 AM (TIMESTAMP(6) format).
What I wanted to do is select all records whose creation time is 24 hours earlier than current time
So what I was going to do was subtract 1 from current time and compare it. But when I subtract 1 it returns only the date.
select * from user where created_date < SYSTIMESTAMP-1
dbms_output.put_line (SYSTIMESTAMP-1);-->29-NOV-20
The time parts are missing which makes me unable to compare with created time in the table
Please help me to complete this task.
If you subtract 1 from a date datatype (e.g. sysdate), it'll move you back one day. But, if you subtract it from a timestamp datatype value, Oracle will convert it to date and return a date (moreover, it'll be truncated).
See the following example:
SQL> select
2 systimestamp val1,
3 systimestamp - 1 val2,
4 --
5 systimestamp - interval '1' day val3
6 from dual;
VAL1
-----------------------------------------------------
VAL2
--------
VAL3
-----------------------------------------------------
30.11.20 09:55:01,439352 +01:00
29.11.20
29.11.20 09:55:01,439352000 +01:00
SQL>
So, what you should do is to subtract an interval, i.e.
select *
from user
where created_date < systimestamp - interval '1' day;
Half the problem is that whatever client program is being used to display the values is using the default date format for their territory and that default format is set to DD-MON-RR.
You can change the NLS_DATE_FORMAT and NLS_TIMESTAMP_FORMAT session parameters and that will (assuming your client program uses them and not some internal settings) give you the output you are expecting:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9';
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF9TZR';
Then
SELECT SYSDATE, SYSTIMESTAMP FROM DUAL;
Outputs (depending on your system time zone):
SYSDATE | SYSTIMESTAMP
:------------------ | :----------------------------------
2020-11-30 10:12:22 | 2020-11-30 10:12:22.476282000+00:00
If you use SYSTIMESTAMP-1 then Oracle does not support subtracting a NUMBER data type from a TIMESTAMP [WITH TIME ZONE] data type but it does support subtracting a NUMBER data type from a DATE data type and will perform an implicit cast from TIMESTAMP to DATE so that the query is valid.
For example:
SELECT SYSDATE - 1, SYSTIMESTAMP - 1, SYSTIMESTAMP - INTERVAL '1' DAY FROM DUAL;
Outputs:
SYSDATE-1 | SYSTIMESTAMP-1 | SYSTIMESTAMP-INTERVAL'1'DAY
:------------------ | :------------------ | :----------------------------------
2020-11-29 10:24:02 | 2020-11-29 10:24:02 | 2020-11-29 10:24:02.651735000+00:00
You can see that in the middle column SYSTIMESTAMP-1 gives the same output as SYSDATE-1 but in the right-hand column, subtracting an interval has ensured that TIMESTAMP WITH TIME ZONE data type is maintained.
So your query:
SELECT * FROM user WHERE created_date < SYSTIMESTAMP-1
Is effectively:
SELECT * FROM user WHERE created_date < CAST( SYSTIMESTAMP AS DATE )-1
Which will have exactly the same year, month, day, hour, minute and (integer) second components but will lose the fractional seconds and time zone information from the SYSTIMESTAMP.
If your column does not have time zone data and the level of precision in the fractional seconds does not matter to you then your query will work adequately.
However, if you want to keep the time zone and/or fractional seconds information then you can use:
SELECT * FROM user WHERE created_date < SYSTIMESTAMP - INTERVAL '1' DAY;
However, if created_date is a DATE column, you probably want:
SELECT * FROM user WHERE created_date < SYSDATE - INTERVAL '1' DAY;
or
SELECT * FROM user WHERE created_date < SYSDATE - 1;
db<>fiddle here
You can use it as (SYSDATE, -1).
Also, if you want to search for new records within 24 hours, it should be "created_date> = (sysdate-1)".

Trying to convert datetime in date in oracle

Hi i'm trying to convert date 01-03-2020 10:48:27 which obtained from query
SELECT
LAST_DAY( ADD_MONTHS(SYSDATE,-3 ) )+1
FROM
dual;
into '01-Mar-2020' but not able to do trying many concept
eg.
trunc(SELECT LAST_DAY( ADD_MONTHS(SYSDATE , - 3 ) )+1 FROM dual),'YEAR')
and
SELECT TRUNC(TO_DATE('SELECT LAST_DAY( ADD_MONTHS(SYSDATE , - 3 ) )+1 FROM dual','DD-MON-YY'), 'YEAR') "New Year" FROM DUAL;
but getting error
Any idea would be appreciated
You're making things way too complicated. Oracle TRUNC takes an additional parameter to specify whatever time interval to truncate to:
SELECT TRUNC(some_date_here, 'MON') FROM dual
If you put some_date_here as sysdate, then currently it will return 01-May-2020 until next month when it starts returning 01-Jun-2020
You can truncate to any interval; TRUNC 01/01/2000 12:34:56 with 'MI' will return 01/01/2000 12:34:00. Truncating to DD is the default (cut the time off). Truncating to DAY sets the date back to the day that started the week in the country oracle thinks it is in (probably a Sunday or Monday)
More info: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions230.htm#i1002084
As I understood your problem you want to go from the current date, to the first of the month that was between 2 and < 3 months ago (so if it's May now, you want to go back to first of March until it's June, when you want to go back to first of April)
If you hence, in the current date of 5th May, want to go back to a date of 1 March, take 2 months off the current date and then TRUNC to the start of the month:
SELECT TRUNC(ADD_MONTHS(sysdate, -2), 'MON') FROM dual
Don't forget you can TRUNC to the nearest quarter of a year, so if you're doing a report that is "the current quarter", then looking at a variation of TRUNC(sysdate, 'Q') would be the way to go
Lastly, I'd urge you NOT to use oracle to convert your dates to strings (in most cases) - if you keep it as a date all the way 'tIl it hits the user's computer it can be formatted for their regional preferences. If you make a decision as to the format as its coming out the dB it makes it much harder to deliver a good international experience for your app
"Convert" in your case means TO_CHAR; alter session is here to set default format for this session.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select
2 last_Day(add_months(sysdate, -3)) + 1 orig,
3 to_char(last_day(add_months(sysdate, -3)) + 1, 'dd-Mon-yyyy', 'nls_Date_language = english') result
4 from dual;
ORIG RESULT
------------------- --------------------
01.03.2020 07:25:44 01-Mar-2020
SQL>
Or, if you altered the session, you'd get it as
SQL> alter session set nls_date_language = 'english';
Session altered.
SQL> alter session set nls_date_format = 'dd-Mon-yyyy';
Session altered.
SQL> select
2 last_Day(add_months(sysdate, -3)) + 1 orig
3 from dual;
ORIG
-----------
01-Mar-2020
SQL>
But, yes - usually we TO_CHAR it.

Oracle SQL Roll back date to beginning of month best practice CONCAT & SUBSTR or TRUNC

I have a field date which is a date format.
It outputs like this for example.
09-NOV-14
Now what i want the output to be is any date rolled back to the 1st of its month.
01-NOV-14
What i did to achieve this is
CONCAT('01',SUBSTR(table.date,3))
Is this the most efficient/best practice way of doing this?
moved from comment to answer:
trunc(date,'month')
The output format you get when a date is cast to string is configurable:
SQL> SELECT SYSDATE FROM DUAL;
SYSDATE
---------
26-NOV-14
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> SELECT SYSDATE FROM DUAL;
SYSDATE
-------------------
2014-11-26 16:15:44
... thus your approach is not particularly robust. To use date functions (rather than string manipulation) please check Make date time's first day of its month.

Get Exact timestamp value?

I am trying to subtract some days from 'current_timestamp' and converting that to timestamp using to_timestamp() function in Oracle. But I am always getting start of day time, that is 12 AM.
When I execute
select to_timestamp(current_timestamp - 3) from dual;
It will give me result like,
18-FEB-14 12.00.00.000000000 AM
But I need exact deduction of 3 days from current time.
Thanks!!!!
select current_timestamp - 3 ts from dual;
or
SELECT SYSTIMESTAMP - INTERVAL '3' DAY AS day FROM dual;
Will give you time as well:
select sysdate - 3 from dual;
Edit based on your comment:
select to_timestamp(to_char(sysdate-3,'DD-Mon-RR HH24:MI:SS'),'DD-Mon-RR HH24:MI:SS') from dual;
Or more simply:
select systimestamp - 3 from dual
An important difference is that SYSDATE gives you server time, and CURRENT_TIMESTAMP gives you session time.
Also, according to the documentation, TO_TIMESTAMP operates on CHAR, VARCHAR2, NCHAR, or NVARCHAR2 data types, not DATE. So I think you need to look elsewhere:
SELECT CAST (SYSDATE AS TIMESTAMP) from dual;