Какой самый эффективный способ запустить конкретный запрос Select?
-
16-10-2019 - |
Вопрос
Если я запускаю следующий код:
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)
Это даст вам план, подобный
Другие советы
Вот как я реформировал ваш запрос. (Сначала я опубликую ваш запрос с вашим планом выполнения, а затем следит за моим новым запросом и соответствующим планом запроса)
Ваш запрос
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
p.PolicyNumber,
p.decpageid,
p.Risk
from StatRiskDecpages p
where decpageid in
(
select max(decpageid)
from StatRiskDecpages
where PolicyNumber = p.PolicyNumber
)
Это показывает план выполнения этого:
Обратите внимание на одностороннее сканирование (в отличие от двух таблиц), а также отсутствие вложенных петель для присоединения.
Что касается того, что выглядит лучше и более поддерживается, я думаю, что они оба относительно работоспособны. Просто некоторые идеи и графическое представление альтернативы.
@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;
Вы также можете подумать о том, чтобы оставить политикуммер из набора результатов. Вы уже знаете, что это такое, так как вы передали его, и это те же избыточные данные в каждом ряду.