If your data is correctly indexed with the ID column from each table as the primary key, then I don't see this query slowing down much as the data grows.
You are worrying prematurely, I think.... but, the purpose of the query is complicated... it is almost as if you are tying to find a random lead to prompt people to look in to 'next'.... where that lead has not been handled in some way yet.
I think you may have better performance with a cursor.... (in a stored procedure?).
Still, even if you have to do the large checks of all the 'handled' leads, you may find it faster to do just the one 'big' subselect instead of multiple smaller ones. you will need to test this on your system to get an idea of the performance.
with (
SELECT LeadID FROM LeadFollowups
UNION
SELECT LeadID FROM LeadsWorking
UNION
SELECT LeadID FROM LeadsDead
UNION
SELECT LeadID FROM LeadHolds
) as handled
select TOP 1 leads.ID
from Leads leads
where leads.ID >= (RAND() * (SELECT MAX(ID) FROM Leads))
and leads.ID not in (select LeadID from handled)
ORDER BY leads.QualityScore DESC
I don't like that your query can return zero results when the RAND()
value is large... and all higher ID's are handled.
As a cursor / procedure, it will process much less data, and, as a consequence, it will likely be faster. The big difference is that it will terminate early (when it has found a valid answer), rather than calculating all the valid answers, and selecting one of them.
It could be something like:
declare @leadid as int;
declare @count as int = 0;
declare LEADCURSOR cursor for
select leads.ID
from Leads leads
where leads.ID >= (RAND() * (SELECT MAX(ID) FROM Leads))
ORDER BY leads.QualityScore DESC
open LEADIDS
fetch next from LEADIDSinto @leadid
while @@FETCH_STATUS = 0
begin
select @count = count(*)
from LeadFollowups, LeadsWorking, LeadsDead, LeadHolds
where LeadFollowups.leadID = @leadid
and LeadsWorking.leadID = @leadid
and LeadsDead.leadID = @leadid
and LeadHolds.leadID = @leadid
if (@count = 0)
BREAK
fetch next from LEADIDSinto @leadid
end
close LEADIDS
deallocate LEADIDS
if (@count <> 0)
set @leadid = null
select @leadid
l.ID >= (RAND() * (SELECT MAX(ID) FROM Leads))
and why do you need this? – Malachi Feb 25 at 16:57