Reputation: 69
I have a field c_days
in the table my_table
that accepts numeric values from 1 to 31.
In this field, numbers from 1 to 9 are single digits.
I am writing a condition, if c_day
is greater than today, then you need to display c_day
in the to_date
date format, if less, then display c_day
in the date format, only the next month.
For example, c_day
is 14, and today we have the 8th number, so you need to display the date 14.02.2023, If c_day
is equal to 5, then you need to display the date of the next month 05.03.2023
I did something like this:
SELECT
C_DAY,
CASE
WHEN C_DAY >= TO_CHAR(SYSDATE, 'DD') THEN
TO_DATE(C_DAY || '.' || TO_CHAR(SYSDATE, 'MM') || '.' || TO_CHAR(SYSDATE, 'YYYY'), 'dd.mm.yyyy')
WHEN C_DAY < TO_CHAR(SYSDATE, 'DD') THEN
TO_DATE(C_DAY || '.' || TO_CHAR(SYSDATE, 'MM') || '.' || TO_CHAR(SYSDATE, 'YYYY'), 'dd.mm.yyyy')
WHEN C_DAY IS NULL THEN
null
END AS new_field
FROM my_table
The problem is that the end result is not converted to the date format, I thought it's cause of that the dates can be displayed as 1.03.2023, 7.03.2023, so i tried convert it into
TO_CHAR(C_DAY, 'fm00')
and did this:
SELECT
C_DAY,
CASE
WHEN TO_CHAR(C_DAY, 'fm00') >= TO_CHAR(SYSDATE, 'DD') THEN
TO_DATE(TO_CHAR(C_DAY, 'fm00') || '.' || TO_CHAR(SYSDATE, 'MM') || '.' || TO_CHAR(SYSDATE, 'YYYY'), 'dd.mm.yyyy')
WHEN TO_CHAR(C_DAY, 'fm00') < TO_CHAR(SYSDATE, 'DD') THEN
TO_DATE(TO_CHAR(C_DAY, 'fm00') || '.' || TO_CHAR(SYSDATE, 'MM') || '.' || TO_CHAR(SYSDATE, 'YYYY'), 'dd.mm.yyyy')
WHEN C_DAY IS NULL THEN
null
END AS new_field
FROM my_table
But its not even working, it shows ora error
Upvotes: 0
Views: 115
Reputation: 167784
You can do it without any string-to-date (or vice-versa) conversions using:
SELECT C_DAY,
LEAST(
ADD_MONTHS(
TRUNC(SYSDATE, 'MM'),
CASE WHEN c_day <= EXTRACT(DAY FROM SYSDATE) THEN 0 ELSE 1 END
) + c_day - 1,
LAST_DAY(
ADD_MONTHS(
TRUNC(SYSDATE, 'MM'),
CASE WHEN c_day <= EXTRACT(DAY FROM SYSDATE) THEN 0 ELSE 1 END
)
)
) AS new_field
FROM my_table
Which, for the sample data:
CREATE TABLE my_table(c_day) AS
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 31;
Outputs:
C_DAY | NEW_FIELD |
---|---|
1 | 2023-02-01 00:00:00 |
2 | 2023-02-02 00:00:00 |
3 | 2023-02-03 00:00:00 |
4 | 2023-02-04 00:00:00 |
5 | 2023-02-05 00:00:00 |
6 | 2023-02-06 00:00:00 |
7 | 2023-02-07 00:00:00 |
8 | 2023-02-08 00:00:00 |
9 | 2023-03-09 00:00:00 |
10 | 2023-03-10 00:00:00 |
11 | 2023-03-11 00:00:00 |
12 | 2023-03-12 00:00:00 |
13 | 2023-03-13 00:00:00 |
14 | 2023-03-14 00:00:00 |
15 | 2023-03-15 00:00:00 |
16 | 2023-03-16 00:00:00 |
17 | 2023-03-17 00:00:00 |
18 | 2023-03-18 00:00:00 |
19 | 2023-03-19 00:00:00 |
20 | 2023-03-20 00:00:00 |
21 | 2023-03-21 00:00:00 |
22 | 2023-03-22 00:00:00 |
23 | 2023-03-23 00:00:00 |
24 | 2023-03-24 00:00:00 |
25 | 2023-03-25 00:00:00 |
26 | 2023-03-26 00:00:00 |
27 | 2023-03-27 00:00:00 |
28 | 2023-03-28 00:00:00 |
29 | 2023-03-29 00:00:00 |
30 | 2023-03-30 00:00:00 |
31 | 2023-03-31 00:00:00 |
Upvotes: 2
Reputation: 59436
As far as I understand your question, one solution could be this one
SELECT
C_DAY,
CASE
WHEN C_DAY >= TO_CHAR(SYSDATE, 'DD') THEN
ADD_MONTHS(TO_DATE(TO_CHAR(SYSDATE, 'YYYY-MM-')||C_DAY , 'YYYY-MM-DD'), 1)
WHEN C_DAY < TO_CHAR(SYSDATE, 'DD') THEN
TO_DATE(TO_CHAR(SYSDATE, 'YYYY-MM-')||C_DAY , 'YYYY-MM-DD')
END AS new_field
FROM my_table
The ADD_MONTHS
function works as this:
If
date
is the last day of the month or if the resulting month has fewer days than the day component ofdate
, then the result is the last day of the resulting month. Otherwise, the result has the same day component asdate
.
Upvotes: 1
Reputation: 142720
Here's one option:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> WITH
2 my_table (c_day)
3 AS
4 (SELECT 14 FROM DUAL
5 UNION ALL
6 SELECT 5 FROM DUAL
7 UNION ALL
8 SELECT 30 FROM DUAL)
9 SELECT c_day,
10 TO_DATE (
11 LPAD (LEAST (c_day, TO_CHAR (LAST_DAY (SYSDATE), 'dd')), 2, '0')
12 || '.'
13 || TO_CHAR (
14 CASE
15 WHEN c_day < TO_CHAR (SYSDATE, 'dd')
16 THEN
17 ADD_MONTHS (SYSDATE, 1)
18 ELSE
19 SYSDATE
20 END,
21 'mm.yyyy'),
22 'dd.mm.yyyy') AS result
23 FROM my_table;
C_DAY RESULT
---------- ----------
14 14.02.2023
5 05.03.2023
30 28.02.2023
SQL>
Upvotes: 1