【问题标题】:Refactor overheaded T-SQL query重构开销的 T-SQL 查询
【发布时间】:2013-12-20 12:46:16
【问题描述】:

有没有办法重构这个查询,使其不再进行如此多的 GetRemainingAmount(@Id) 函数调用?我尝试在选择块中命名它,例如Amount 然后在 Where and Group 中使用它是编译错误。

 SELECT SomeAccountId ,
        GetRemainingAmount(@Id) ,
        Iso
 FROM   Accounts
 WHERE  GetRemainingAmount(@Id) > 0
 GROUP BY SomeAccountId ,
        GetRemainingAmount(@Id) ,
        Iso 

【问题讨论】:

  • 粘贴GetRemainingAmount()的代码
  • SELECT 中的 CROSS APPLY 将在字段中给出结果,然后您可以在 WHERE/GROUP BY 中使用; stackoverflow.com/questions/3196851/…
  • 粘贴?不会改变任何东西,GetRemainingAmount 是一个耗时的函数,我想避免那些重复调用它。
  • WHERE 子句中的标量 UDF 是一种反模式。您没有其他谓词,因此它将始终为Accounts 中的每一行评估它。如果您向我们展示它的代码,我们可能会建议一个替代方案。
  • Martin Smith 提出了最重要的一点。您可以减少必须键入该代码的次数,但 where 子句只会在为所有行运行该函数后消除行。在计算每一行的金额之前,不可能知道金额是否大于 0。

标签: sql-server performance tsql refactoring


【解决方案1】:

您总是可以这样做,使用 CTE(通用表表达式)来隔离该调用并只执行一次:

;WITH CTE AS 
(
   SELECT 
      SomeAccountId,
      RemainingAmount = GetRemainingAmount(@Id),
      Iso
   FROM   
      Accounts 
)
SELECT
    SomeAccountId, RemainingAmount, Iso
FROM 
    CTE
WHERE  
    RemainingAmount > 0
GROUP BY 
    SomeAccountId,
    RemainingAmount,
    Iso 

但老实说,如果没有像 SUMAVG 这样的聚合函数,我首先看不到 GROUP BY 子句的意义......

【讨论】:

  • GROUP BY 仍然可以消除重复项,但它似乎可以被 DISTINCT 替换。
【解决方案2】:

可以使用 distinct 来消除 GROUP BY

SELECT  distinct 
        SomeAccountId ,
        GetRemainingAmount(@Id) ,
        Iso
 FROM   Accounts
 WHERE  GetRemainingAmount(@Id) > 0

【讨论】:

    【解决方案3】:

    或者你可以推导出来:

    select 
        SomeAccountId,
        RemainingAmount,
        Iso
    from (
        SELECT 
            SomeAccountId,
            GetRemainingAmount(@Id) as RemainingAmount,
            Iso
        FROM Accounts
    ) _Data
    WHERE RemainingAmount > 0
    GROUP BY 
        SomeAccountId,
        RemainingAmount,
        Iso 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      相关资源
      最近更新 更多