You have a bunch of OR conditions. I would suggest replacing them with not exists :
SELECT s.supplier_id FROM supplier_info s WHERE s.creation_date >= TRUNC(SYSDATE) - INTERVAL '6' MONTH OR NOT EXISTS (SELECT 1 FROM purchase_order_line_all po WHERE s.supplier_id = po.vendor_no AND po.state IN ('Closed', 'Cancelled') ) AND NOT EXISTS (SELECT 1 FROM purchase_req_line_all pr WHERE s.supplier_id = pr.vendor_no AND r.state IN ('PO Created', 'Cancelled') ) EXISTS (SELECT 1 FROM man_supp_invoice m WHERE s.supplier_id = m.IDENTITY AND m.invoice_date >= TRUNC(SYSDATE) - INTERVAL '18' MONTH );
I am sure your performance problem is caused by Cartesian products. If the supplier has 100 order lines, as well as 100 req lines and 100 invoices, then the connection creates 100 * 100 * 100 = 1,000,000 lines for only one supplier. This is a large staging table.
Instead, instead of EXISTS Oracle will not create giant staging tables.
In addition, you can test performance by adding one sentence at a time.
Finally, I am not 100% sure if the logic is correct for average conditions. For example, you really want this for the first not exists :
EXISTS (SELECT 1 FROM purchase_order_line_all po WHERE s.supplier_id = po.vendor_no AND po.state NOT IN ('Closed', 'Cancelled') ) AND
As written, your logic is that at least one state is not 'Closed' or 'Cancelled' , which makes the above option. I affirm that no state is 'Closed' or 'Cancelled' , simply because it made more sense to me.
source share