Как избежать оператора сортировки в запросе на выборку

В моем операторе выбора у меня есть простой подзапрос, который захватывает последний ExpirationDate в пределах ControlNo.

Этот подзапрос значительно снижает производительность. QuoteID это Clustered index за столом tblQuotes

Статистика актуальна.

SELECT
  ControlNo,
  PolicyNumber,
(     
  SELECT TOP 1 Q.ExpirationDate
  FROM tblQuotes Q 
  WHERE Q.ControlNo = tblQuotes.ControlNo
  ORDER BY Q.QuoteID DESC
 )
SUM(Premium) as Premium
FROM tblQuotes
GROUP BY ...

введите здесь описание изображения

введите здесь описание изображения

Можно ли найти обходной путь в этом случае?


person Serdia    schedule 23.02.2019    source источник
comment
индекс на ControlNo,QuoteID include (ExpirationDate) должен избавиться как от сортировки, так и от катушки   -  person Martin Smith    schedule 23.02.2019


Ответы (2)


Попробуйте заменить подзапрос:

(     
  SELECT TOP 1 Q.ExpirationDate
  FROM tblQuotes Q 
  WHERE Q.ControlNo = tblQuotes.ControlNo
  ORDER BY Q.QuoteID DESC
 )

С функцией Windows, если вы ищете максимальное значение

MAX(ExpirationDate) OVER(PARTITION BY ControlNo)

Если вы ищете первое значение в определенном порядке, используйте:

FIRST_VALUE(ExpirationDate) OVER(PARTITION BY ControlNo ORDER BY QuoteID DESC)
person Hadi    schedule 23.02.2019
comment
Потрясающий! Большое спасибо! - person Serdia; 25.02.2019

Если последняя запись содержит Latest ExpirationDate, просто используйте оператор MAX, как показано ниже:

  SELECT
    ControlNo,
    PolicyNumber,
    MAX(ExpirationDate) ExpirationDate,
    SUM(Premium) as Premium
  FROM tblQuotes
  GROUP BY ControlNo, PolicyNumber;

Однако, если ExpirationDate не всегда является последним, и вы просто хотите получить значение любой последней записи, я бы предложил аналогично ниже. Сначала получите значение QouteID (при условии, что это PK), прежде чем ExpirationDate будет сведен к минимуму при сортировке при поиске значения истечения срока действия.

SELECT q.*, qx.ExpirationDate 
FROM 
  (
    SELECT ControlNo, PolicyNumber, SUM(Premium) as Premium
    FROM tblQuotes t
    GROUP BY ControlNo, PolicyNumber
  ) q
  OUTER APPLY
  (
    SELECT ExpirationDate
    FROM tblQuotes q2
    WHERE q2.QuoteID=(SELECT MAX(QouteID) MaxQouteID FROM tblQuotes q1 WHERE q1.ContolNo=q.ControlNo)
  ) qx;
person DominicV    schedule 23.02.2019