Какой самый эффективный способ запустить конкретный запрос Select?

dba.stackexchange https://dba.stackexchange.com/questions/14989

Вопрос

Если я запускаю следующий код:

select PolicyNumber, MAX(decpageid) as decpageid, Risk  
from StatRiskDecpages 
where PolicyNumber = 'AR-0000301132-04'
group by PolicyNumber, Risk

Я получаю следующие результаты:

PolicyNumber    decpageid   Risk
AR-0000301132-04    41        1
AR-0000301132-04    41        2
AR-0000301132-04    37        3

Все, что я действительно хочу получить, - это полиция и максимальный decpageID (который в данном случае будет 41) вместе с числами риска (которые должны быть 1 и 2)

Запрос также возвращает DecpageID 37, даже если он не является максимальным decpageID для политикуации, потому что он имеет другой риск.

Результаты, которые я хотел бы вернуть, являются:

PolicyNumber    DecpageID   Risk
AR-0000301132-04    41       1
AR-0000301132-04    41       2

Я выяснил 2 разных запроса, которые я могу использовать, чтобы вернуть желаемые результаты, но я не думаю, что они самые эффективные. Запросы, которые я придумал:

select PolicyNumber,  MAX(decpageid) as decpageid, Risk 
from StatRiskDecpages 
where 
       PolicyNumber = 'AR-0000301132-04' 
   and decpageid = (
      select MAX(decpageid) 
      from StatRiskDecpages 
      where PolicyNumber = 'AR-0000301132-04' 
   )
;

Это возвращает желаемые результаты, но я не хочу указывать номер политики более раз в запросе. Есть ли способ вызвать полицинумбер в подпрограмму из внешнего запроса?

Другой запрос, который я придумал, был:

select  t1.PolicyNumber,t2.DecpageID, t2.Risk
from (
   select PolicyNumber, MAX(decpageid) as decpageid 
   from StatRiskDecpages 
   where PolicyNumber = 'AR-0000301132-04'
   group by PolicyNumber
) as t1 
   left join StatRiskDecpages as t2 
      on  t1.PolicyNumber = t2.PolicyNumber 
      and t1.decpageid = t2.DecpageID
;

Мне нравится этот запрос, потому что мне нужно только указать полицинумеры, и я также могу расширить запрос, чтобы я мог вернуть информацию для нескольких политицинов.

Что мне нужно знать, так это то, является ли это наиболее эффективным способом написания запроса? Это кажется немного избыточным. Я мог бы ошибаться, но я думаю, что может быть лучший более эффективный способ написания запроса. Какие-либо предложения?

Это было полезно?

Решение

Я бы, наверное, использовал

SELECT TOP (1) WITH TIES PolicyNumber, 
                         decpageid, 
                         Risk 
FROM   StatRiskDecpages 
WHERE  PolicyNumber = 'AR-0000301132-04' 
ORDER  BY decpageid DESC 

Предполагая индекс покрытия на (PolicyNumber, decpageid) INCLUDE(Risk) Это даст вам план, подобный

enter image description here

Другие советы

Вот как я реформировал ваш запрос. (Сначала я опубликую ваш запрос с вашим планом выполнения, а затем следит за моим новым запросом и соответствующим планом запроса)

Ваш запрос

Select  
    t1.PolicyNumber,
    t2.DecpageID, 
    t2.Risk
from
(
    select 
        PolicyNumber, 
        MAX(decpageid) as decpageid 
    from StatRiskDecpages 
    where PolicyNumber = 'AR-0000301132-04'
    group by PolicyNumber
) as t1 
left join StatRiskDecpages as t2 
on t1.PolicyNumber = t2.PolicyNumber 
and t1.decpageid = t2.DecpageID

План выполнения вашего запроса заключается в следующем:

enter image description here

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

Мой запрос

select
    p.PolicyNumber,
    p.decpageid,
    p.Risk
from StatRiskDecpages p
where decpageid in
(
    select max(decpageid)
    from StatRiskDecpages
    where PolicyNumber = p.PolicyNumber
)

Это показывает план выполнения этого:

enter image description here

Обратите внимание на одностороннее сканирование (в отличие от двух таблиц), а также отсутствие вложенных петель для присоединения.

Что касается того, что выглядит лучше и более поддерживается, я думаю, что они оба относительно работоспособны. Просто некоторые идеи и графическое представление альтернативы.

@ypercube делает хороший момент, что элегантный Ищу Запрос не обязательно означает, что он будет более эффективным. Я понятия не имею о ваших индексах или размере данных, но вы можете сравнить следующую версию функции оконных функций с существующими запросами (я бы проверил как продолжительность, так и качество планов):

;WITH x AS 
(
  SELECT PolicyNumber, decpageid, Risk,
    dr = DENSE_RANK() OVER (ORDER BY decpageid DESC)
   FROM dbo.StatRiskDecpages
   WHERE PolicyNumber = 'AR-0000301132-04'
) 
SELECT PolicyNumber, decpageid, Risk
  FROM x
  WHERE dr = 1;

Вы также можете подумать о том, чтобы оставить политикуммер из набора результатов. Вы уже знаете, что это такое, так как вы передали его, и это те же избыточные данные в каждом ряду.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top