I’m trying to optimise my query. Basically I have an Department table and a document table. Each document belongs to a department and each document can be a specific type.
Currently mu query looks like this
SELECT DepartmentID,
[Description] = DepartmentNo + ' (' + DepartmentName + ')',
hasInvoice = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 1) > 0 THEN 1 ELSE 0 END,
hasCreditNote = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 2) > 0 THEN 1 ELSE 0 END,
hasQuote = CASE WHEN EXISTS(SELECT DocID FROM Document WHERE DepartmentID = Department.DepartmentID AND TypeID = 3) > 0 THEN 1 ELSE 0 END
FROM Department
ORDER BY DepartmentName
The problem I have is that for each lookup of the documents relating to the department by their type causes the query to rescan through the document table which makes things really slow. Is there a more optimised way of doing this? I’ve tried using a CTE, Doing a left join for each type. but it seems to make no impact to making the query faster.
We have roughly 200000 documents, so it’s quite an important thing to get this query optimised.
Thanks
Whatever the indexes, you have too many “touches” on the Document table: 3 times per row in the Department table. So it will scale badly and the optimiser may not change the correlated sub-queries into JOINs.
You can do with a single “touch” on the Document table like this using a JOIN
You can also LEFT JOIN 3 times on an filtered+aggregated Document derived table or use CROSS APPLY 3 times: but these are still 3 uses of the Document table
You need an index on
DepartmentID, TypeIDin Documents for any solution. Without this, I’ve only re-arranged the deck chairs so to speakI assume Department.DepartmentID is a clustered index too.