【问题标题】:TSQL: Trying to Streamline/Optimise my Stored-ProcedureTSQL:尝试简化/优化我的存储过程
【发布时间】:2019-12-17 00:13:13
【问题描述】:

大家下午好,

我编写了一个存储过程,它可以工作并且执行速度相对较快,因为它只是进行相当简单的计算。我想你可以说我的过程本身的问题是 SELECT 和 ORDER BY 子句中重复的“CASE 语句”的数量。我的 TSQL 知识仍然相当 N00bish,因为我充其量仍然是一个“P”板。是否可以进一步简化我的代码,以便我只有 CASE WHEN 计算出现一次,并且我可以继续在多个地方使用它?我相信这对于将来的校对会更好,而且我只需要在根语句处进行更改,而不必在多个位置进行更改!

@Officer_Name 是从用户界面传入的变量。如您所见,F_YEAR(财政年度)、F_Quarter(财政季度)字段计算在语句的 Order By 部分中再次重复,我想知道是否可以避免这种情况:) 非常感谢您提前拯救了这个 damoiseau苦恼中,我希望有一个慷慨的 TSQL 水平更高的专家可以帮我这个忙!非常感谢。

    BEGIN

    SELECT  TOP (100) PERCENT 
    COUNT(DISTINCT(dbo.TableA.[Account ID])) AS Applications,
    SUM(CASE WHEN [Client Claims] LIKE '%claim%' THEN 1 ELSE 0 END) AS Main_Client,
    COUNT([TableA_ID]) AS Clients,
    (CASE
    WHEN [Finalised date] < '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) THEN 'PAST CASES'
    WHEN [Finalised date] BETWEEN '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2)  AND '06/30/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 1) THEN 'YEAR'
    WHEN MONTH([Finalised date]) BETWEEN 1  AND 3  THEN ' Q3'
    WHEN MONTH([Finalised date]) BETWEEN 4  AND 6  THEN ' Q4'
    WHEN MONTH([Finalised date]) BETWEEN 7  AND 9  THEN ' Q1'
    WHEN MONTH([Finalised date]) BETWEEN 10 AND 12 THEN ' Q2'
    END) AS F_Quarter, 
    (CASE 
    WHEN [Finalised date] < '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) THEN CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) + ' & Older'
    WHEN MONTH([Finalised date]) BETWEEN 1  AND 6 THEN convert(char(4), YEAR([Finalised date]) - 0)
    WHEN MONTH([Finalised date]) BETWEEN 7  AND 12 THEN convert(char(4), YEAR([Finalised date]) + 1) 
    ELSE convert(char(4), YEAR([Finalised date])) 
    END) AS F_YEAR

FROM    dbo.TableB INNER JOIN
        dbo.TableA ON dbo.TableB.[Account ID] = dbo.TableA.[Account ID] LEFT OUTER JOIN
        dbo.Officers ON dbo.TableA.[Account Officer] = dbo.Officers.FullName

WHERE   [Case Officer] = @Officer_Name AND [Finalisation] IS NOT NULL

GROUP BY 
    (CASE 
    WHEN [Finalised date] < '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) THEN CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) + ' & Older'
    WHEN MONTH([Finalised date]) BETWEEN 1  AND 6 THEN convert(char(4), YEAR([Finalised date]) - 0)
    WHEN MONTH([Finalised date]) BETWEEN 7  AND 12 THEN convert(char(4), YEAR([Finalised date]) + 1) 
    ELSE convert(char(4), YEAR([Finalised date])) 
    END),
    (CASE
    WHEN [Finalised date] < '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2) THEN 'PAST CASES'
    WHEN [Finalised date] BETWEEN '07/01/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 2)  AND '06/30/' +  CONVERT(VARCHAR(4), DATEPART(Year,GETDATE()) - 1) THEN 'YEAR'
    WHEN MONTH([Finalised date]) BETWEEN 1  AND 3  THEN ' Q3'
    WHEN MONTH([Finalised date]) BETWEEN 4  AND 6  THEN ' Q4'
    WHEN MONTH([Finalised date]) BETWEEN 7  AND 9  THEN ' Q1'
    WHEN MONTH([Finalised date]) BETWEEN 10 AND 12 THEN ' Q2'
    END)

ORDER BY F_YEAR DESC, F_Quarter
END

【问题讨论】:

    标签: tsql stored-procedures future-proof streamline


    【解决方案1】:

    您可以将 CASE 表达式放在 CTE 中,并在后面的查询中通过其别名多次引用它。但是,由于 F_YEAR 的 CASE 表达式与 F_Quarter 的 CASE 表达式不同,因此无法对整个查询仅使用一个 CASE 表达式。在伪代码中,您可以这样做:

    WITH cte AS (
       SELECT ...
       , {CASE Expression for year} AS F_Year
       , {CASE Expression for quarter} AS F_Quarter
       FROM...
    )
    SELECT ... F_Year, F_Quarter
    FROM ... WHERE ...
    GROUP BY F_Year, F_Quarter ...
    

    【讨论】:

    • 嗨Tab,非常感谢您的输入,我刚刚尝试了CTE。但是,它仍然不会让我删除 GROUP BY 子句中的第二个 Case When 语句。计算需要按 CASE WHEN 语句中的输出值分组,因此我进退两难。我想知道是否有一种方法可以将这些 CASE WHEN 声明为变量或类似的变量,以便我只有完整的 case when 语句出现一次以供将来证明和提高效率。
    • 是的,如果操作正确,它将允许您在 GROUP BY 子句中删除 CASE 表达式。你是怎么做到的? GROUP BY 需要在主查询中;不在 CTE 中。
    • 嗨,Tab,我刚刚明白了您正确执行此操作的意思。我在 CTE 中包含了 GROUP BY 语句,因此服务器希望我在 CTE 中也重复 CASE WHEN 语句。正如您在示例中向我展示的那样,我已从 CTE 中删除了 GROUP BY 语句以坐在下面,并且它运行良好!非常感谢您的意见!您的反馈有效地帮助我简化了至少 10 到 15 个其他存储过程!如果有机会,我会为你喝啤酒!!
    猜你喜欢
    • 1970-01-01
    • 2021-04-17
    • 2010-10-01
    • 1970-01-01
    • 2012-02-26
    • 2018-04-03
    • 1970-01-01
    相关资源
    最近更新 更多