Reputation: 83
I have three tables, customers, orders and customers-orders like this:
Customers:
ID NAME
1 Peter
2 Jack
3 Lisa
Orders:
ID INIT_DATE END_DATE
1 10-11-2014 10-11-2015
2 23-11-2014 01-01-2015
3 23-11-2014 03-05-2015
4 04-04-2016 08-11-2016
5 13-07-2016 01-11-2016
6 04-06-2016 30-10-2016
7 12-11-2014 01-05-2015
8 26-11-2014 10-10-2015
9 05-09-2016 11-11-2016
Customers_Orders:
CUSTOMER_ID ORDER_ID
1 1
1 2
1 3
2 4
2 5
2 6
3 7
3 8
3 9
I need to get customers who have all orders outdated. I mean, those orders which sysdate is not between init_date and end_date. In this case, the expected result is 1-Peter.
What i tried is this:
SELECT *
FROM Customers
WHERE
ID NOT IN (
SELECT DISTINCT Customers_Orders.CUSTOMER_ID
FROM Customers_Orders, Orders
WHERE Customers_Orders.ORDER_ID = Orders.ID
AND Orders.INIT_DATE <= SYSDATE AND Orders.END_DATE > SYSDATE
)
But i don't like the "NOT IN" syntax because the low performance. Is there another way?
Note: date format is dd-mm-yyyy
Edit: I corrected the question (in bold).
Upvotes: 0
Views: 69
Reputation: 11195
This will exclude all customers where the INIT_DATE is less than today and the END_DATE > today.
with Curr_ord as
(
select co1.customer_id, co1.order_id
from customers_orders co1
inner join orders o1
on o1.id = co1.order_id
where o1.INIT_DATE <= sysdate
and o1.END_DATE > sysdate
)
select C1.*
from Customers C1
left join Curr_Ord CO2
on C1.Customer_ID = CO2.Customer_ID
where CO2.Customer_ID is null
Upvotes: 2
Reputation: 4055
Why not just do the join?
SELECT DISTINCT C.CUSTOMER_ID
FROM customers c
JOIN Customers_Orders co on co.customer_id = c.customer_id
JOIN Orders od on od.order_id = co.order_id
WHERE Od.INIT_DATE <= SYSDATE
AND Od.END_DATE > SYSDATE
With the right indexing on orders, you might get the performance gain by putting the filter into the join:
SELECT DISTINCT C.CUSTOMER_ID
FROM customers c
JOIN Customers_Orders co on co.customer_id = c.customer_id
JOIN (SELECT od.order_id
from Orders
WHERE Od.INIT_DATE <= SYSDATE
AND Od.END_DATE > SYSDATE ) od on od.order_id = co.order_id
but now we're talking performance tuning strategies.... and in this case we would need to talk about your data profiles etc to get the optimal solution.
Upvotes: -1
Reputation: 49260
Join the three tables and use conditional aggregation to check if all the orders for a customer are outdated.
select c.id,c.name
from customer_orders co
join orders o on o.id=co.order_id
join customers c on c.id=co.customer_id
group by c.id,c.name
having count(case when sysdate between co.init_date and co.end_date then 1 end) = 0
Upvotes: 2