Замена в подзапросе (для вывода одной строчки) TOP(1) и ORDER BY на оконную функцию ROW_NUMBER()

Tsql теория > Замена в подзапросе (для вывода одной строчки) TOP(1) и ORDER BY на оконную функцию ROW_NUMBER()
31.05.2018 11:00:56


Наиболее часто встречающиеся слова в статье:

[BusinessEntityID] [ROW_NUMBER] [операции] [IndexSeek] [подзапросе] [строчки] [оконную]


Статья:

Замена в подзапросе (для  вывода одной строчки) TOP(1) и ORDER BY на оконную функцию ROW_NUMBER()

Использование операции TOP заставляет оптимизатор форсировать использование IndexSeek. К таким же последствиям приводит использованием OUTER/CROSS APPLY вместе с TOP:

 
SELECT p.BusinessEntityID
, (
SELECT TOP(1) s.SalesQuota
FROM Sales.SalesPersonQuotaHistory s
WHERE s.BusinessEntityID = p.BusinessEntityID
ORDER BY s.QuotaDate DESC
)
FROM Person.Person p
 
SELECT p.BusinessEntityID
, t.SalesQuota
FROM Person.Person p
OUTER APPLY (
SELECT TOP(1) s.SalesQuota
FROM Sales.SalesPersonQuotaHistory s
WHERE s.BusinessEntityID = p.BusinessEntityID
ORDER BY s.QuotaDate DESC
) t
При их выполнении будет возникать одна и та же проблема — множественные IndexSeek операции:

Вооружившись оконной функцией, перепишем запрос:

SELECT p.BusinessEntityID
, t.SalesQuota
FROM Person.Person p
LEFT JOIN (
SELECT s.BusinessEntityID
, s.SalesQuota
, RowNum = ROW_NUMBER() OVER (PARTITION BY s.BusinessEntityID ORDER BY s.QuotaDate DESC)
FROM Sales.SalesPersonQuotaHistory s
) t ON p.BusinessEntityID = t.BusinessEntityID
AND t.RowNum = 1