'Find all Boxes containing files where all the files of the box have expiration date inferior to a DATE

Title was complicated, here the request: I want to select boxes (box). All files (file) from a box need to have an expiration date inferior to '01/01/2022'; so does the box.

Here is a request not working, but giving the good JOIN :

select distinct b.code,b.EXPIRATION_DATE
from box b
join COMPONENT_A cpp on cpp.b_Id=b.Id
join COMPONENT_Z cpt on cpt.A_Id=cpp.Id
join file f on f.Z_Id =cpt.Id
where 
b.EXPIRATION_DATE < to_date('01.01.2022', 'dd.mm.yyyy')
 and f.EXPIRATION_DATE < to_date('01.01.2022', 'dd.mm.yyyy');

This request does not work because it still gives boxes where some files inside have EXPIRATION_DATE > to_date('01.01.2022', 'dd.mm.yyyy')

What I need Example :

Box_1(01/01/2001) : file1(01/01/1999); file2(01/01/2023) NOT SELECTED (because file 2)

Box_2(01/01/2024) : file1(01/01/1999); file2(01/01/2002) NOT SELECTED (box date)

Box_3(01/01/2001) : file1(01/01/1999); file2(01/01/2001) SELECTED (all < 01/01/2022)

I am sure there is a Group by somewhere, file table is a huge table so performance is important.



Solution 1:[1]

If expiration_date columns' datatype is DATE, then don't compare them to strings. Use date literal or TO_DATE function with appropriate format mask. Both options below:

where b.EXPIRATION_DATE < date '2022-01-01'
  and f.EXPIRATION_DATE < to_date('01.01.2022', 'dd.mm.yyyy')

As of the query itself, you didn't post sample data (CREATE TABLE and INSERT INTO statements; it is difficult for us to guess what might be written in those 4 tables) so I created my own, simplified test case.

I removed component% tables, but - what might be useful here - is the temp CTE which returns max expiration_date for each box - then you'd use it in the final query.

Something like this:

SQL> with box (code, expiration_date) as
  2    (select 'Box_1', date '2001-01-01' from dual union all
  3     select 'Box_3', date '2001-01-01' from dual
  4    ),
  5  tfile (code, cfile, expiration_date) as
  6    (select 'Box_1', 'file1', date '1999-01-01' from dual union all
  7     select 'Box_1', 'file2', date '2023-01-01' from dual union all
  8     --
  9     select 'Box_3', 'file1', date '1999-01-01' from dual union all
 10     select 'Box_3', 'file2', date '2001-01-01' from dual
 11    ),
 12  --
 13  temp as
 14    -- find MAX expiration_date for each box code
 15    (select code, max(expiration_date) expiration_date
 16     from tfile
 17     group by code
 18    )
 19  select b.code, b.expiration_date
 20  from box b join temp f on f.code = b.code
 21  where b.expiration_date < date '2022-01-01'
 22    and f.expiration_date < date '2022-01-01';

CODE  EXPIRATION
----- ----------
Box_3 01.01.2001

SQL>

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