Reputation: 647
Need some help with this query, I just want to know if what I am doing is fine or do I need JOIN to get it better. Sorry if this a silly question but I am little worried as I query the same table thrice. Thanks in advance
Select *
from TableA
where (A_id in (1, 2, 3, 4)
and flag = 'Y') or
(A_id in
(select A_id from TableB
where A_id in
(Select A_id from TableA
where (A_id in (1, 2, 3, 4)
and flag = 'N')
group by A_id
having sum(qty) > 0)
)
Relation between TableA and TableB is one-to-many
Condition or Logic:
Upvotes: 0
Views: 61
Reputation: 77
Would it be possible for you to split this query into a store procedure?
In Example:
DELIMITER $$
CREATE FUNCTION flaggedSelection ( my_flag varchar(1) )
RETURNS varchar(255) -- TODO: change to appropriate output
BEGIN
DECLARE return_value varchar(255); -- TODO: change to appropriate output
IF flag = 'Y'
THEN
-- Performe select without further checks
-- return_value = QUERY;
ELSE
-- Refer TableB to see if sum of the qty column is greater than 0
-- return_value = QUERY;
END IF;
RETURN return_value;
END; $$
DELIMITER;
Upvotes: -1
Reputation: 6449
There's nothing badly wrong with the query you've presented, but there are improvements that can be made. If you move the test for Flag='N' into your first select from TableA and correlate your select from TableB with your first select from TableA, then you can dispense with the second select from TableA:
Select *
from TableA A
where A_id in (1, 2, 3, 4)
and (flag = 'Y'
or (flag = 'N'
and A_id in (select A_id
from TableB B
where b.A_id = a.A_id
group by A_id
having sum(qty) > 0))
);
This will eliminate an extra lookup on TableA for information that should already be known. Second since TableA.A_Id is now correlated with TableB.A_Id, the A_Id in (...)
can be changed to an exists clause:
Select *
from TableA A
where A_id in (1, 2, 3, 4)
and (flag = 'Y'
or (flag = 'N'
and exists (select A_id
from TableB B
where b.A_id = a.A_id
group by A_id
having sum(qty) > 0))
);
This may (depending on the database type) inform the databases query optimizer that it can stop retrieving rows from TableB after the first row is found.
In an Oracle database on a small unindexed sample dataset these two changes shaved 25% off of the cost of the query, so the performance increases could be significant.
Upvotes: 1
Reputation: 94894
Your approach is indeed way too complicated. Select from A where flag = Y or the sum of related B > 0. Do the latter in a subquery.
select *
from a
where a_id in (1,2,3,4)
and
(
flag = 'Y'
or
(select sum(qty) from b where b.a_id = a.a_id) > 0
)
Upvotes: 2