【问题标题】:Improvise SQL query即兴 SQL 查询
【发布时间】:2016-04-26 12:41:25
【问题描述】:

我有下面的 sql,它需要 1 或 2 秒才能返回结果。我在游标内调用此 SQL 500 多次。我正在尝试重写此查询。

SELECT Sum(CASE 
                WHEN UpdatedAdjustedOT IS NOT NULL
                    AND UpdatedAdjustedOT != ''
                    AND UpdatedAdjustedOT != '0'
                    THEN CONVERT(DECIMAL(18, 2), UpdatedAdjustedOT)
                ELSE 0
                END) AS OTHours
    FROM tbl_OTAuthorization
    WHERE EmployeeCodeFK = @EmployeeCode
        AND month(OTDate) = Month(@FromDate)
        AND year(OTDate) = Year(@FromDate)

请建议我如何以更好的方式重写此查询

【问题讨论】:

  • 调用这个的外部查询是什么?这本身看起来并不那么昂贵,但是如果您在游标中使用它,那么我们需要查看外部查询以了解它在做什么。
  • 光标中有员工列表。我必须通过在这个 SQL 中传递员工代码来找到其他人
  • 问题出在您的光标上,所以发布所有代码,我们可以提供帮助
  • 看起来 CASE 语句是不必要的。只需SUM(UpdatedAdjustedOT) 并将这些条件添加到您的 WHERE 子句中...WHERE UpdatedAdjustedOT IS NOT NULL AND UpdatedAdjustedOT != '' AND UpdatedAdjustedOT != '0'
  • 所以您已经询问了代码中非常具体的部分的问题(这意味着您不知道如何修复它)。不止一位评论者建议发布外部代码,希望我们能找到更好的解决方案,但您知道吗?顺便说一句,基于集合的方法会击中这些表一次,而不是像你的光标那样击中 500 多次)

标签: sql sql-server sql-server-2008 sql-server-2012 sql-server-2008-r2


【解决方案1】:

不要过滤函数结果。找到一种方法来替换它:

AND month(OTDate) = Month(@FromDate)
AND year(OTDate) = Year(@FromDate)

到这样的事情:

 and OTDate >= the first day of the month for @FromDate
 and OTDate < the first day of the month following @FromDate

【讨论】:

    【解决方案2】:

    首先,将WHERE 子句重写为如下所示:

    SELECT . . .
    FROM tbl_OTAuthorization
    WHERE EmployeeCodeFK = @EmployeeCode AND
          OTDate >= DATEADD(day, 1 - DAY(@FromDate), @FromDate) AND
          OTDate < DATEADD(month, 1, DATEADD(@FromDate, 1 - DAY(@FromDate), @FromDate));
    

    其次,为表创建合适的索引:

    CREATE INDEX tbl_OTAuthorization_2 ON tbl_OTAuthorization(EmployeeCodeFK, OTDate, UpdatedAdjustedOT);
    

    第三,返回并修复您的代码,使其不会在员工和日期之间循环。您应该能够在单个查询中处理逻辑。一般来说,如果您想优化使用数据库的性能,请避免使用游标。

    【讨论】:

    • 谢谢戈登林诺夫
    【解决方案3】:

    试试这个:

    SELECT Sum(CONVERT(DECIMAL(18, 2), ISNULL(NULLIF(UpdatedAdjustedOT, ''), 0))) as OTHours
        FROM tbl_OTAuthorization
        WHERE EmployeeCodeFK = @EmployeeCode
            AND month(OTDate) = Month(@FromDate)
            AND year(OTDate) = Year(@FromDate)
    

    【讨论】:

      【解决方案4】:
      WHERE EmployeeCodeFK = @EmployeeCode
          AND OTDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, @FromDate), 0)
          AND OTDate < DATEADD(MONTH, 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, @FromDate), 0))
      

      【讨论】:

        猜你喜欢
        • 2011-07-24
        • 1970-01-01
        • 2012-08-22
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2012-03-08
        • 2012-04-10
        相关资源
        最近更新 更多