T-SQL SELECT with child rows exists optimise
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 slo开发者_开发问答w. 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
SELECT
D.DepartmentID,
[Description] = D.DepartmentNo + ' (' + D.DepartmentName + ')',
hasInvoice = SIGN(COUNT(CASE WHEN doc.TypeID = 1 THEN 1 END)),
hasCreditNote = SIGN(COUNT(CASE WHEN doc.TypeID = 2 THEN 1 END)),
hasQuote = SIGN(COUNT(CASE WHEN doc.TypeID = 3 THEN 1 END))
FROM
Department D
LEFT JOIN
Document doc ON D.DepartmentID = doc.DepartmentID
ORDER BY
D.DepartmentName, D.DepartmentID, D.DepartmentNo
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, TypeID
in Documents for any solution. Without this, I've only re-arranged the deck chairs so to speak
I assume Department.DepartmentID is a clustered index too.
精彩评论