'Oracle YEAR logic
I have 2 tables. First table TABLE1 has 3 columns (ROLLNO, CODE, ADM_DT).
CREATE TABLE TABLE1
( ROLLNO VARCHAR2(3) NOT NULL,
CODE VARCHAR2(3) NOT NULL,
ADM_DT TIMESTAMP(3) NOT NULL
);
Second table TABLE2 has 3 columns (CODE, YEAR).
CREATE TABLE TABLE2
(
CODE VARCHAR2(3) NOT NULL,
YEAR VARCHAR2(4) NOT NULL
);
TABLE1 has few records mentioned below:
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('100','ABC', '12-NOV-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('101','ACD', '12-DEC-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('102','ABD', '15-JAN-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('103','DEF', '14-AUG-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('104','DFE', '17-JUL-21 12.00.00.000000000 AM');
INSERT INTO TABLE1(ROLLNO, CODE, ADM_DT) VALUES ('105','FED', '21-SEP-21 12.00.00.000000000 AM');
ROLLNO CODE ADM_DT
-----------------------------------
100 ABC 12-NOV-21 12.00.00.000000000 AM
101 ACD 12-DEC-21 12.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.000000000 AM
103 DEF 14-AUG-21 12.00.00.000000000 AM
104 DFE 17-JUL-21 12.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.000000000 AM
TABLE2 has few records mentioned below:
INSERT INTO TABLE2(CODE, YEAR) VALUES ('ABC','2022');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('ADC','2022');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('DEF','2021');
INSERT INTO TABLE2(CODE, YEAR) VALUES ('DFE','2021');
CODE YEAR
-------------
ABC 2022
ADC 2022
DEF 2021
DFE 2021
I need to select the records from TABLE1 in such a way that
1) fetch the month present in ADM_DT value and if month is between Sep and Dec and also the year, then check the CODE value present in YEAR+1 of TABLE2, if present then don't select the record from TABLE1 else select.
Ex: Let us take a record of ROLLNO = '102' and CODE is 'ABC' and it has ADM_DT as '12-NOV-21 12.00.00.00.000000000 AM' so here month is November and the year is 2021, so check whether CODE 'ABC' present in TABLE2 with YEAR '2022'...code 'ABC' present in TABLE2, then don't select this record from TABLE1.
2) fetch the month present in ADM_DT value and if month is between Jan and Aug, then check the CODE value present in YEAR of TABLE2, if present then don't select the record from TABLE1 else select.
Ex: Let us take a record of ROLLNO = '103' and CODE is 'DEF' and it has ADM_DT as '14-AUG-21 12.00.00.00.000000000 AM' so here month is August and the year is 2021 so check whether CODE 'DEF' present in TABLE2 with YEAR '2021'...code 'DEF' present in TABLE2, then don't select this record from TABLE1.
This is the Result table I need:
ROLLNO CODE ADM_DT
------------------------------------------------
101 ACD 12-DEC-21 12.00.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.00.000000000 AM
This is the Result table I am getting:
ROLLNO CODE ADM_DT
------------------------------------------------
100 ABC 12-NOV-21 12.00.00.000000000 AM (This shouldn't get picked up as this record has Month as Nov and year as 2021, so we need to go to the TABLE2 and check whether we have CODE 'ABC' in the YEAR '2022', its present so it shouldn't pick up)
101 ACD 12-DEC-21 12.00.00.000000000 AM
102 ABD 15-JAN-21 12.00.00.000000000 AM
105 FED 21-SEP-21 12.00.00.000000000 AM
This is the query I have tried:
SELECT * FROM TABLE1 T1
WHERE NOT EXISTS (
SELECT 1 FROM TABLE2 T2
WHERE T1.CODE = T2.CODE
AND EXTRACT(YEAR FROM T1.ADM_DT) =
CASE
WHEN EXTRACT(MONTH FROM(T1.ADM_DT)) BETWEEN 9 AND 12 THEN TO_NUMBER(T2.YEAR)+1
WHEN EXTRACT(MONTH FROM(T1.ADM_DT)) BETWEEN 1 AND 8 THEN TO_NUMBER(T2.YEAR)
END
);
Is this correct query? because I have executed this query and it gave me wrong result...might be issue with YEAR logic I have written in query (Need to use NOT EXISTS query).
Solution 1:[1]
You can create a range from the table2.year rather than trying to match the years based on the month in table1.adm_dt. This has the added bonus that Oracle can use an index on the table1.adm_dt column whereas your query would not use an index and would need separate function-based indexes for each of the EXTRACT functions for MONTH and YEAR.
Either:
SELECT t1.*
FROM table1 T1
LEFT OUTER JOIN table2 T2
ON (t1.code = t2.code
AND t1.adm_dt >= TO_DATE((t2.year - 1) || '-09-01', 'YYYY-MM-DD')
AND t1.adm_dt < TO_DATE(t2.year || '-09-01', 'YYYY-MM-DD')
)
WHERE t2.code IS NULL;
or:
SELECT *
FROM table1 T1
WHERE NOT EXISTS (
SELECT 1
FROM table2 T2
WHERE t1.code = t2.code
AND t1.adm_dt >= TO_DATE((t2.year - 1) || '-09-01', 'YYYY-MM-DD')
AND t1.adm_dt < TO_DATE(t2.year || '-09-01', 'YYYY-MM-DD')
);
Which, for your sample data, both output:
ROLLNO CODE ADM_DT 102 ABD 15-JAN-21 00.00.00.000 105 FED 21-SEP-21 00.00.00.000 101 ACD 12-DEC-21 00.00.00.000
db<>fiddle here
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MT0 |
