运行特定选择查询的最有效方法是什么?

Jua*_*lez 6 performance sql-server-2008 sql-server subquery query-performance

如果我运行以下代码:

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

我得到以下结果:

PolicyNumber    decpageid   Risk
AR-0000301132-04    41        1
AR-0000301132-04    41        2
AR-0000301132-04    37        3
Run Code Online (Sandbox Code Playgroud)

我真正想要检索的是policynumber和最大decpageid(在这种情况下为41)以及风险数字(应该是1和2)

该查询还返回 decpageid 37,即使它不是 policynumber 的最大 decpageid,因为它具有不同的风险。

我想返回的结果是:

PolicyNumber    DecpageID   Risk
AR-0000301132-04    41       1
AR-0000301132-04    41       2
Run Code Online (Sandbox Code Playgroud)

我已经想出了 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' 
   )
;
Run Code Online (Sandbox Code Playgroud)

这将返回所需的结果,但我不想在查询中多次指定策略编号。有没有办法从外部查询将 policynumber 调用到子查询中?

我想出的另一个查询是:

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
;
Run Code Online (Sandbox Code Playgroud)

我喜欢这个查询,因为我只需要指定 policynumber 1 次,我还可以扩展查询,以便我可以返回多个 policynumber 的信息。

我需要知道的是,这是否是编写查询的最有效方式?似乎有点多余。我可能是错的,但我认为可能有更好更有效的方式来编写查询。有什么建议?

Mar*_*ith 8

我可能会用

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

假设这个覆盖索引(PolicyNumber, decpageid) INCLUDE(Risk)会给你一个计划

在此处输入图片说明

  • 有趣的是,我们被新功能所束缚,以至于忘记了像“TOP WITH TIES”这样的旧备用。PS 没有双关语的意思。好吧也许吧。 (6认同)

Tho*_*ger 6

这是我重构您的查询的方式。(首先我将您的查询与您的执行计划一起发布,然后是我的新查询和相应的查询计划)

您的查询

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
Run Code Online (Sandbox Code Playgroud)

您的查询的执行计划如下:

在此处输入图片说明

然后我写了这样的查询,给出了相同的期望结果:

我的查询

select
    p.PolicyNumber,
    p.decpageid,
    p.Risk
from StatRiskDecpages p
where decpageid in
(
    select max(decpageid)
    from StatRiskDecpages
    where PolicyNumber = p.PolicyNumber
)
Run Code Online (Sandbox Code Playgroud)

这显示了一个执行计划:

在此处输入图片说明

请注意单个表扫描(与您的两个表扫描相反),以及缺少用于 JOIN 的嵌套循环。

至于什么看起来更好,更易于维护,我认为它们都是相对可行的。只是替代方案的一些想法和图形表示。