Reputation: 4919
I have table containing users like so:
user_id | status
----------------
1 | 1
2 | 2
3 | 1
4 | 1
And table containing orders
order_id | user_id | status
---------------------------
1 | 1 | 1
2 | 2 | 1
3 | 2 | 2
4 | 2 | 1
5 | 3 | 1
And table containing ordered products
order_id | cash
----------------
1 | 10
1 | 20
1 | 10
2 | 10
3 | 10
3 | 10
What I need to select are all users that have status=1 and have exactly one order and that order must have status=1 and sum of all products for that order must be >=30.
So for above data query should return only user with id=1
I've managed to write select procedure but it isn't working fast:
SELECT user_id
FROM users US
WHERE status = 1
AND (SELECT Count(*)
FROM orders ORD
WHERE ORD.user_id = US.user_id) = 1
AND (SELECT Count(*)
FROM orders ORD
WHERE ORD.user_id = US.user_id
AND ORD.status = 1) = 1
AND (SELECT Sum(PRO.cash)
FROM products PRO
JOIN orders ORD
ON PRO.order_id = ORD.order_id
WHERE ORD.user_id = US.user_id) > 30
I would like to improve this a bit so I won't have to use so much inner selects
Upvotes: 2
Views: 981
Reputation: 238296
You can usually get better performance by moving the queries from the where
clause to joins
:
select u.user_id
from Users u
join Orders o
on o.user_id = u.user_id
join Producs p
on p.order_id = o.order_id
group by
u.user_id
having min(u.status) = 1 -- there's only 1 user, so min() is safe
and count(distinct o.order_id) = 1
and min(o.status) = 1 -- there's only 1 order, so min() is safe
and sum(p.cash) > 30
Upvotes: 4
Reputation: 116
SELECT USER_ID
FROM (SELECT US.USER_ID, SUM (PRO.CASH) CASH
FROM USERS US, ORDERS ORD, PRODUCTS PRO
WHERE US.USER_ID = ORD.USER_ID AND ORD.ORDER_ID = PRO.ORDER_ID AND US.STATUS = 1 AND ORD.STATUS = 1)
WHERE CASH > 30
Upvotes: 0