sql-server - 如何过滤 WHERE 子句中的 TOP 1 条件

标签 sql-server performance t-sql sql-server-2012

使用 TOP 1 逻辑消除 WHERE 子句中的记录的最有效方法是什么?

tblQuoteStatusChangeLog 不在JOIN 中。 但根据此表中的值,我需要消除 NewQuoteStatusID = 12

的记录

它的工作方式是这样的,但我正在寻找更有效的方法,因为我的排序(前 N 排序)运算符过于广泛。

SELECT    
    Q.ControlNo   
    ,sum(fid.amtbilled) as Premium


FROM           
    [dbo].tblQuotes Q 
        inner join [dbo].[tblFin_Invoices] FI  on Q.QuoteID = FI.QuoteID and FI.failed = 0  
        inner join [dbo].[tblFin_InvoiceDetails] FID  on FI.[InvoiceNum] = FID.InvoiceNum  
WHERE       (
            SELECT  TOP 1 NewQuoteStatusID
             FROM    tblQuoteStatusChangeLog
             WHERE   (ControlNo = Q.ControlNo)
             ORDER BY Timestamp DESC
             ) <> 12

Group by
Q.ControlNo

enter image description here

最佳答案

您的代码是RBAR ;一次执行同一个子查询1,效率非常低。

您担心“排序”,但这本身并不是问题。进一步查看平面图的上方和左侧;到嵌套循环。看到顶部的胖输入线和下面的瘦输入线。基本上你已经多次命中你的类别了。

建议:尝试使用基于集合的解决方案。 “提前”“准备”WHERE 子句所需的数据,这样就可以消除 RBAR。想象一下,您有 LatestStatus 作为一个包含 ControlNoStatusID 列的表。应用过滤器会简单得多;查询优化器应该能够找到更有效的整体计划。

您可以使用 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 并寻找更加“基于集合”的解决方案。

关于sql-server - 如何过滤 WHERE 子句中的 TOP 1 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52670185/

相关文章:

sql - 如何使用 SQL 中存储过程的值填充结果 View 列?

sql-server - 在 SQL Server 中加载大文本文件

utf-8 - 如何就地反转 UTF-8 字符串?

t-sql - 如何在sql中计算大组合量

sql-server - 解析带有多个分隔符的整数值的 SQL 字符串

mysql - 获取重复记录以显示在同一行中

sql - 如何返回没有公共(public) ID 的另一个表中尚不存在的行

t-sql - t/sql 中的 Excel 参数 SELECT TOP xxx 不使用 SP

ruby-on-rails - 加速我的 Rails 应用程序,它使用 Typhoeus 发出多个 Web 服务 HTTP 请求

c++ - 如何查看应用程序的工作时间?