如何在WHERE子句中过滤TOP 1条件

时间:2018-10-05 16:53:28

标签: sql-server performance tsql sql-server-2012

使用// Static method var v1 = createVector(2, 3, 4); var v2 = createVector(1, 2, 3); var v3 = p5.Vector.sub(v1, v2); // v3 has components [1, 1, 1] print(v3); 逻辑消除WHERE子句中的记录的最有效方法是什么?

TOP 1不在tblQuoteStatusChangeLog中。 但是基于此表中的值,我需要消除JOIN = 12

的记录

它按原样工作,但是我正在寻找更有效的方法,因为我的Sort(Top N Sort)运算符过于庞大。

NewQuoteStatusID

enter image description here

1 个答案:

答案 0 :(得分:3)

您的代码为CMake Doc;一次执行相同的子查询1,效率非常低。

您担心“排序”,但是它本身就不是问题。在计划的左上方看;到嵌套循环。请参阅顶部的胖输入行,以及下方的细行。基本上,您的击中次数很多次。

建议:尝试使用基于集合的解决方案。 “预先”准备“ WHERE”子句所需的数据,因此可以消除RBAR。假设您有LatestStatus作为具有ControlNoStatusID列的表。应用过滤器会容易得多;并且Query Optimiser应该能够找到更有效的总体计划。

您可以使用CTE进行设置。

;with StatusByControlNo as (
  SELECT  ROW_NUMBER() OVER(PARTITION BY ControlNo ORDER BY Timestamp DESC) AS RowNo,
          ControlNo, Timestamp, NewQuoteStatusID
  FROM    tblQuoteStatusChangeLog
) ...
/*Easy to get Latest status per ControlNo from here*/
SELECT  ControlNo, NewQuoteStatusID
FROM    StatusByControlNo
WHERE   RowNo = 1

现在只需进行一些调整,您的查询就会变成:

;with StatusByControlNo as (
  SELECT  ROW_NUMBER() OVER(PARTITION BY ControlNo ORDER BY Timestamp DESC) AS RowNo,
          ControlNo, Timestamp, NewQuoteStatusID
  FROM    tblQuoteStatusChangeLog
)
SELECT    
    Q.ControlNo,
    sum(fid.amtbilled) as Premium
FROM           
    tblQuotes Q 
    inner join tblFin_Invoices FI
        on Q.QuoteID = FI.QuoteID and FI.failed = 0
    inner join tblFin_InvoiceDetails FID
        on FI.InvoiceNum = FID.InvoiceNum
    inner join StatusByControlNo S
        on S.ControlNo = Q.ControlNo and S.RowNo = 1
WHERE
    S.ControlNo <> 12
Group by Q.ControlNo

它应该说可以尝试多种变体。但是核心原则是减少RBAR并寻找更“基于集合”的解决方案。