I am working with an Oracle Datebase and I want to convert a date to null when it is more than a certain number of months from today.
The date format I am using is dd-mm-yy
So lets say you have this table:
WITH TEST_TABLE as (select '1' as num, '10-FEB-16' from dual
union(select '2', '10-FEB-30' from dual)
union(select '3', '10-FEB-50' from dual)
union(select '4', '10-FEB-17' from dual))
I know I can use: SELECT SYSDATE FROM DUAL; to get todays date but I am not sure how to compare this by months.
How would I change the dates to null when they are greater than say 24 months from today?
Something like this:
update test_table
set dte = (case when add_months(dte, -12) < sysdate then dte end);
Note: You should be storing a date as a date data type in the database. The output format (by default) is the DD-MMM-YY format. But that is just the date formatted for output.
Related
TABLE NAME = CONTRACT_DATA
CONTRACT DATE
A 10/25/2019
B 06/20/2019
C 10/01/2019
D 10/05/2019
Query:
select *
from CONTRACT_DATA
WHERE DATE(VALUE_DATE,'MM/DD/YYYY') > '10/01/2019' AND
DATE(VALUE_DATE,'MM/DD/YYYY') < '10/31/2019'
Tried to get the data in Oct month but failed
Required output A,C,D
In Oracle a DATE data type always has a year, month, day, hour, minute and second components. Your user interface may not show the time component but it is always there. If its not specified then it will default to 00:00:00 (midnight) but you should not rely on this.
Also, dates do not have a format. They are stored internally as 7 bytes (2 for year and 1 for each other month-second component). It is the user interface you are using that will implicitly apply a format to your data when you want to display it so that it is meaningful to the user.
You can specify dates using:
ANSI date literals: DATE '2019-10-01'
ANSI timestamp literals: TIMESTAMP '2019-10-01 12:34:56' (and Oracle will cast it to a date as needed)
The TO_DATE function: TO_DATE( '10/01/2019', 'MM/DD/YYYY' )
If you have a DATE column then do not use TO_DATE on it as it is already a DATE; instead just compare it to another DATE.
If you want the dates for October 2019 then you need to find the values between 2019-10-01 00:00:00 and 2019-10-31 23:59:59 and the simplest way to do this is to find values that are greater than or equal to midnight of the first day of the month and less than midnight of the first day of the next month:
Test Data:
CREATE TABLE contract_data (
CONTRACT CHAR(1),
VALUE_DATE DATE
);
INSERT INTO contract_data
SELECT 'A', DATE '2019-10-25' FROM DUAL UNION ALL
SELECT 'B', DATE '2019-06-20' FROM DUAL UNION ALL
SELECT 'C', DATE '2019-10-01' FROM DUAL UNION ALL
SELECT 'D', DATE '2019-10-05' FROM DUAL UNION ALL
SELECT 'E', TIMESTAMP '2019-10-31 23:59:59' FROM DUAL;
Query:
SELECT *
FROM contract_data
WHERE VALUE_DATE >= DATE '2019-10-01'
AND VALUE_DATE < DATE '2019-11-01'
Output:
CONTRACT | VALUE_DATE
:------- | :---------
A | 10/25/2019
C | 10/01/2019
D | 10/05/2019
E | 10/31/2019
db<>fiddle here
You would need to convert your string to date for comparison, using TO_DATE(); on the other side of the operator, for fixed values, you can use a DATE litteral:
SELECT *
FROM contract_data
WHERE
TO_DATE(value_date, 'MM/DD/YYY') > DATE'2019-10-01'
AND TO_DATE(value_date, 'MM/DD/YYY') < DATE'2019-10-31'
Note: if you want the entire month, then you need to ajust the boundaries
SELECT *
FROM contract_data
WHERE
TO_DATE(value_date, 'MM/DD/YYY') >= DATE'2019-10-01'
AND TO_DATE(value_date, 'MM/DD/YYY') < DATE'2019-11-01'
If your date is stored as string in the table then you can simply use the to_date function and DATE literal as following:
select *
from CONTRACT_DATA
WHERE TO_DATE(VALUE_DATE,'MM/DD/YYYY')
BETWEEN DATE '2019-10-01' AND DATE '2019-10-31'
Cheers!!
Oracle table in my application has a column with name "transaction_date" of type string. It stores date in the format MMDD, where MM = month and DD = day.
Please help me to write a SQL statement which will compare the transaction_date column with the current system date, if transaction_date is less than or equal to 120 days, then fetch the records from the table.
The problem I am facing is, transaction_date in db does not have year just month and day as a string value, so how to check if that value is not more than 120 days, that check should work if value in column is of previous year. For example, SQL should work for the scenario where current system date is lets say 01 feb 2018, and the transaction_date column in table has value "1225" (25th dec of previous year).
As a general disclaimer, your current table design is sub optimal, because a) you are storing dates as text, and b) you are not even storing the year for each date. From what you wrote, it looks like you want to consider all data as having occurred within the last year, from the current date.
One trick we can try here is to compare the MMDD text for each record in your table against TO_CHAR(SYSDATE, 'MMDD'), using the following logic:
If the MMDD is less than or equal to today, then it gets assigned to current year (2018 as of the time of writing this answer)
If the MMDD is greater than today, then it gets assigned to previous year (2017).
Then, we may build dates for each record using the appropriate year and check if it is within 120 days of SYSDATE.
WITH yourTable AS (
SELECT '0101' AS date_col FROM dual UNION ALL
SELECT '1001' FROM dual UNION ALL
SELECT '1027' FROM dual UNION ALL
SELECT '1215' FROM dual
)
SELECT
date_col
FROM yourTable
WHERE
(date_col <= TO_CHAR(SYSDATE, 'MMDD') AND
TO_DATE(date_col || TO_CHAR(SYSDATE, 'YYYY'), 'MMDDYYYY') >= SYSDATE - 120) OR
(date_col > TO_CHAR(SYSDATE, 'MMDD') AND
TO_DATE(date_col ||
TO_CHAR(TRUNC(ADD_MONTHS(SYSDATE, -12), 'YEAR'), 'YYYY'), 'MMDDYYYY') >=
SYSDATE - 120);
Demo
I want to select data where the operation_date between '01-Jan-2016' and yesterday. I used code as follows:
select *
where operation_date between '01-Jan-2016' and sysdate-1
from TABLE
But sysdate returns both date and time. Therefore, the above output includes all the data between '01-Jan-2016' and say, 14 Nov-2017 09:50:51. I only want the data before today. How to convert current time to date without time? Thanks.
Seems that you are looking for trunc().
Example
SELECT sysdate - 1 AS current_Date_Time
,trunc(sysdate) - 1 AS CURRENT_DATE1
,trunc(sysdate - 1) AS CURRENT_DATE2
FROM dual
Result
CURRENT_DATE_TIME CURRENT_DATE1 CURRENT_DATE2
----------------------------------------------------------
13.11.2017 18:08:41 13.11.2017 00:00:00 13.11.2017 00:00:00
DEMO
So the correct query will be as below.
SELECT *
WHERE operation_date BETWEEN DATE '2016-01-01' -- ANSI Date Literal
AND trunc(sysdate - 1)
FROM TABLE
OR
SELECT *
WHERE operation_date BETWEEN DATE '2016-01-01' -- ANSI Date Literal
AND trunc(sysdate) - 1
FROM TABLE
How can I select data between two date with hours. My oracle column date's format is:10.04.2006 19:10:37 I can select between twou days with:
select date from table where date between '1/1/2011' and '2/1/2011
but I will select between hours which hours are in date column i.e:
select date from table where date between '1/1/2011 22:00'and '2/1/2011 21:00' what can I do
You can use to_date to specify a custom date format:
where date between to_date('1/1/2011 22:00', 'DD/MM/yyyy HH24:MI')
and to_date('2/1/2011 21:00', 'DD/MM/yyyy HH24:MI')
This is the way I usually do.
where date between date'2011-1-1'+22/24 and date'2011-1-2'+21/24
On the column
TRUNC(date_col)+hours/24
I have a column named StartDate containing a date in this format: 03-03-2012 15:22
What I need is to convert it to date. It should be looking like this: DD/MM/YYYY
What I have tried without success is:
select
p1.PA_VALUE as StartDate,
p2.PA_VALUE as EndDate
from WP_Work p
LEFT JOIN PARAMETER p1 on p1.WP_ID=p.WP_ID AND p1.NAME = 'StartDate'
LEFT JOIN PARAMETER p2 on p2.WP_ID=p.WP_ID AND p2.NAME = 'Date_To'
WHERE p.TYPE = 'EventManagement2'
AND TO_DATE(p1.PA_VALUE, 'DD/MM/YYYY') >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
AND TO_DATE(p2.PA_VALUE, 'DD/MM/YYYY') <= TO_DATE('26/10/2012', 'DD/MM/YYYY')
Is there a way to do this?
EDIT1: the PA_VALUE column is: VARCHAR2
You can use TRUNC on DateTime to remove Time part of the DateTime. So your where clause can be:
AND TRUNC(p1.PA_VALUE) >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
The TRUNCATE (datetime) function returns date with the time portion of
the day truncated to the unit specified by the format model.
When you convert your string to a date you need to match the date mask to the format in the string. This includes a time element, which you need to remove with truncation:
select
p1.PA_VALUE as StartDate,
p2.PA_VALUE as EndDate
from WP_Work p
LEFT JOIN PARAMETER p1 on p1.WP_ID=p.WP_ID AND p1.NAME = 'StartDate'
LEFT JOIN PARAMETER p2 on p2.WP_ID=p.WP_ID AND p2.NAME = 'Date_To'
WHERE p.TYPE = 'EventManagement2'
AND trunc(TO_DATE(p1.PA_VALUE, 'DD-MM-YYYY HH24:MI')) >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
AND trunc(TO_DATE(p2.PA_VALUE, 'DD-MM-YYYY HH24:MI')) <= TO_DATE('26/10/2012', 'DD/MM/YYYY')
Outside the scope of the question, but storing dates as strings is bad practice, and storing date times is even worse.
We need to convert the strings to dates in order to do any form of date processing (arithmetic, interval assessment, etc) on them
Strings offer no guarantees regarding format, so we run the risk of date corruption crashing our code. We can defend against this by employing VALIDATE_CONVERSION() (available since 12c, find out more ) but it's still a PITN
Using non-standard datatypes makes it harder to reason about the data model and the code we build over it.
We can use TRUNC function in Oracle DB. Here is an example.
SELECT TRUNC(TO_DATE('01 Jan 2018 08:00:00','DD-MON-YYYY HH24:MI:SS')) FROM DUAL
Output:
1/1/2018
Try
SELECT to_char(p1.PA_VALUE,'DD/MM/YYYY') as StartDate,
to_char(p2.PA_VALUE,'DD/MM/YYYY') as EndDate
...
If your column with DATE datatype has value like below : -
value in column : 10-NOV-2005 06:31:00
Then, You can Use TRUNC function in select query to convert your date-time value to only date like - DD/MM/YYYY or DD-MON-YYYY
select TRUNC(column_1) from table1;
result : 10-NOV-2005
You will see above result - Provided that NLS_DATE_FORMAT is set as like below :-
Alter session NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
there is also extended usage like this:
WITH dates AS (
SELECT date'2015-01-01' d FROM dual union
SELECT date'2015-01-10' d FROM dual union
SELECT date'2015-02-01' d FROM dual union
SELECT timestamp'2015-03-03 23:45:00' d FROM dual union
SELECT timestamp'2015-04-11 12:34:56' d FROM dual
)
SELECT d "Original Date",
trunc(d) "Nearest Day, Time Removed",
trunc(d, 'ww') "Nearest Week",
trunc(d, 'iw') "Start of Week",
trunc(d, 'mm') "Start of Month",
trunc(d, 'year') "Start of Year"
FROM dates;
Oracle Offical Help Page