I have a field next_repay_date as varchar2(11).
I need to get the date after 2 days.
Suppose I am having next_repay_date as 25-Sep-2011 as varchar2(11), I should get a result as 27-Sep-2011
Please suggest a solution?
Dates should not be held in char fields - use a Date or datetime
Then add two days - which I think is DBMS sepcific
Step 1, use the correct type for dates, that is, type DATE.
Step 2, use yourdate + INTERVAL 2 DAY (mysql).
Since you are using Oracle this could be done as
SELECT to_date('25-Sep-2007', 'dd-MON-RRRR') + 2 from dual
Date arithmetic is really simply in Oracle, providing we have an actual DATE to work with. So the first step is to cast your column to a DATE datatype, and then you can add or subtract days from it.
SQL> select to_date('27-SEP-2011', 'DD-MON-YYYY') + 2
2 from dual
3 /
TO_DATE('
---------
29-SEP-11
SQL>
Related
I have numbers like 42946 in a database column and i want to format it as a normal Date like dd/mm/yyyy.
I was searching a lot but i dont find anything usefull.
I tried to do TO_DATE(<date>,'J') but this doesn't work beacuse i think 42946 is the number of days between today and January 1 of 1900, and this method works only for dates that are between today and January 1 of 4712 BC.
I hope you can help me with this.
i think 42946 is the number of days between today and January 1 of 1900
You mean, number of days since 1st of January 1900?
If so, you don't have to do much - just add that value to date you specified and you'll get the result. Its (result's) datatype is DATE so you can display it any way you want, using the to_char function (or any other option you prefer):
SQL> select date '1900-01-01' + 42946 as result from dual;
RESULT
----------
01.08.2017
SQL>
Example of formatting it:
SQL> select to_char(date '1900-01-01' + 42946, 'dd-mon-yyyy', 'nls_date_language = english') as result from dual;
RESULT
-----------
01-aug-2017
SQL>
I have a oracle sql query to get me the dates from 18/05/2021 to '28/05/2021'.
For some reason the the value after slash is not read, as the values from month 4 is also outputed. I dont know where i am wrong. Please give a hand if you are able, thanks a lot for your time.
NOTE: the dates have been stored in the database with a varchar datatype.
SELECT datadate
FROM mytable
WHERE trailerid= '1' and datattime>'05:00:00' and datattime<'12:00:00'
AND datadate between '18/05/2021' and '28/05/2021'
GROUP BY datadate ORDER BY datadate;
Current output
DATADATE
----------------
18/05/2021
19/04/2021
19/05/2021
20/05/2021
21/04/2021
21/05/2021
22/04/2021
22/05/2021
23/04/2021
23/05/2021
24/04/2021
24/05/2021
25/04/2021
25/05/2021
26/04/2021
26/05/2021
27/04/2021
27/05/2021
28/04/2021
28/05/2021
That's what happens when people store date values as strings.
See if this helps:
AND to_date(datadate, 'dd/mm/yyyy') between to_date('18/05/2021', 'dd/mm/yyyy')
and to_date('28/05/2021', 'dd/mm/yyyy')
You don't have to start over, just move the data to a datetime column
ALTER TABLE t ADD x DATE;
UPDATE t SET x = to_date(concat(datadate,datatime), 'dd/mm/yyyyhh24:mi:ss'))
WHERE datadate in (SELECT to_char(to_date('1999-12-31', 'yyyy-mm-dd') + level, 'dd/mm/yyyy') FROM dual CONNECT BY level <= 10000)
That WH ERE clause should generate a list of valid dates from 2000 to about 2030 - if you have dates outside this range adjust accordingly
Should now be able to find invalid dates (they weren't part of the where clause and x should hence remain null) and fix manually:
SELECT * FROM t WHERE x is null
Then drop your datadate and datatime cols and rename x to datadatetime
Now queries like BETWEEN work properly, and if you need just the date part you can do TRUNC(x). (You can even TRUNC to other date parts like hours, to cut the minutes and seconds off, or week of year to round dates down to the start of the week etc)
If you need just the time you either do x - TRUNC(x) which gives a decimal number like 0.5 for 12 noon or 0.75 for 6pm, or you can TOCHAR depending on what you want to do. It would be better to do x -TRUNC(x) BETWEEN 9.0/24.0 AND 17.0/24.0 than doing a string compare
Please help to sole this task. I need convert date to char and then to number, so that i can perform arithmetic operation and divide the date by 2.
select (sysdate+30+30+89)/2 from dual;
This query doesn't work and i have no idea how i can convert date to number.
The only sensible reason that I can think of for doing something like this is to get the midpoint of two dates, where one is sysdate.
If that is what you are trying to do, subtract the dates and divide by 2. Dividing an interval in half makes sense. Then add the resulting interval back to one of the dates.
For instance:
select date '2020-01-01' + (sysdate - date '2020-01-01') / 2
from dual
Based on the understanding of the question I think you need the current day of the year to perform arithmetic operation
SELECT (to_number(to_char(sysdate,'DDD'))+30+30+89)/2 from dual;
I have a table that I need to filter based on date. For my problem, I have to filter the record which are relevant only for the current date without the time portion of the date.
For that I have used the following approach. Query seems to be working fine but I would like to know whether there are any pitfalls in this approach.Part of the WHERE clause related to the query is as follows.
AND TO_CHAR(EOD_DATE,'YYYY-MM-DD') IN TO_CHAR(sysdate,'YYYY-MM-DD')
EOD_DATE is the field in the table I take into consideration.I want records that EOD_DATE value is in the current date regardless of the time portion of EOD_DATE.
Thanks in advance :)
DATE datatype is up to a second precise. Therefore:
SQL> select trunc(sysdate) d_from, trunc(sysdate + 1) - 1/(24*60*60) d_to from dual;
D_FROM D_TO
------------------- -------------------
21.06.2018 00:00:00 21.06.2018 23:59:59
says that - if you want to be able to use index on the EOD_DATE column - you should consider
where eod_date between trunc(sysdate)
and trunc(sysdate + 1) - 1/(24*60*60)
Your solution works, but you are using a double conversion to compare strings instead of comparing dates. Besides, you don't need IN but an =
This could be a better, more readable way:
... and trunc(sysdate) = trunc(EOD_DATE)
Simply use TRUNC to remove the time component (or rather set it to 00:00:00) and then compare the dates:
WHERE TRUNC(EOD_DATE) = TRUNC(SYSDATE)
I need to find some records created in a range of quarters. For example, I'm looking for all records created between the 4th quarter of 2008 and the 1st quarter of 2010. I have this in my WHERE-clause:
...and r.record_create_date between to_date('2008 4','YYYY Q')
and to_date('2010 1','YYYY Q')
but Oracle says: ORA-01820: format code cannot appear in date input format. The Q is a valid date format symbol, so I'm not sure what's happened. Is this even a valid way to find values in between calender quarters, or is there a better way?
Also interesting, and possibly related, if I execute this:
select to_date('2009','YYYY') from dual;
The value displayed in my IDE is 2009-08-01. I would have expected 2009-08-04, since today is 2010-08-04.
This:
select to_date('2009 1','YYYY Q') from dual;
of course, fails.
(Oracle 10g)
Oracle says: ORA-01820: format code cannot appear in date input format. The Q is a valid date format symbol, so I'm not sure what's happened.
See the second column of table 2.15 at http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34948. Not all format elements are allowed when converting to dates, timestamps, etc.
I recommend against using between for date range checks. People often will miss values within the ending day that the expect to be included. So I would translate:
and r.record_create_date between to_date('2008 4','YYYY Q')
and to_date('2010 1','YYYY Q')
To
and to_date('2008-10-01', 'YYYY-MM-DD') <= r.record_create_date
and record_create_date < to_date('2010-04-01', 'YYYY-MM-DD') -- < beginning of 2Q2010.
Someone asked the same question on OTN: http://forums.oracle.com/forums/thread.jspa?threadID=1081398&tstart=255
The crux of the issue is that you can not specify "Q" in the TO_DATE function.
Given that you're already specifying a portion of the date, why not provide the entire date? Mind too that to_date('2010 1','YYYY Q') would give you Jan 1st, 2010 when you really want March 31st, 2010... at a second to midnight.
Since the relationship between quarters to months is one-to-many, it doesn't make sense to do TO_DATE('2008 1', 'yyyy q'); what date should be returned? The first of the quarter, the end of the quarter, ...? (On the other hand, converting a date to a quarter - like TO_CHAR(SYSDATE, 'yyyy q') makes sense because a specific date only exists in one quarter.)
So, if you do want a query that looks for a date that falls between two quarters, you will have to "rolll your own" (explicitly stating the dates of the start/end of a quarter.)
As a side note, in case anyone is considering not using TO_DATE please do not use things like: WHERE date_value BETWEEN 'date string1' and 'date string2' without the TO_DATE function. It assumes a default date format and under certain situations can avoid potentially useful indexes altogether.
Below is one example where the same query can have a different result.
select sysdate from dual where sysdate between '1-Jan-10' and '31-Dec-10';
SYSDATE
---------
04-AUG-10
SQL> alter session set nls_date_format = 'YYYY-MM-DD';
Session altered.
SQL> select * from dual where sysdate between '1-Jan-10' and '31-Dec-10';
no rows selected
(Notice that in the second instance no error is returned. It just assumes Jan 10, 0001 and Dec. 10th, 0031.)
I think the best way is to just input the quarter start date and quarter end dates without even bothering with to_date. I think if you use
between '1-Jan-10' and '31-Dec-10'
for example, then you don't (in Oracle I believe) need to_date and it isn't much more difficult than typing in the quarter number
To calculate in Oracle the first day of a quarter and the last day of a quarter from the year and quarter:
I Use the fact
start_month= -2 + 3 * quarter
last_month = 3 * quarter
variable v_year number
variable v_quarter number
exec :v_year :=2017
exec :v_quarter:=4
select :v_year as year,
:v_quarter as quarter,
to_date(:v_year||to_char(-2+3*:v_quarter,'fm00'),'yyyymm') as quarter_start,
last_day(to_date(:v_year||to_char(3*:v_quarter,'fm00')||'01 23:59:59','yyyymmdd hh24:mi:ss')) as quarter_end
from dual a;
YEAR|QUARTER|QUARTER_START |QUARTER_END
2017| 4|2017-10-01 00:00:00|2017-12-31 23:59:59