开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜