聚合 SQL SELECT 语句中的重复 CASE WHEN

Repetitive CASE WHEN in Aggregate SQL SELECT Statements

我正在努力降低我经常使用的查询的成本和大小,它看起来过于重复,不是最有效的处理方式。

简化表示如下:

SELECT [Year],
       [Month],
       COUNT(CASE WHEN Type = 'Quotation' THEN clientID ELSE NULL END),
       COUNT(CASE WHEN Type = 'Purchase' THEN ClientID ELSE NULL END),
       SUM(CASE WHEN Type = 'Purchase' THEN Cost ELSE NULL END)
       ...           
FROM dbo.Example
GROUP BY [Year],[Month]

就尺寸和成本而言,我认为我必须能够 trim 缩小 CASE WHEN ... THEN ELSE NULL END。有什么建议吗?

我正在使用 SQL Server 2008 R2,谢谢。

按类型制作视图怎么样? (报价、采购等)。这样,您可以逐个视图优化并进行连接查询以获得您想要的结果。

我认为这是 'rotate' 一个 table 的推荐方式。

查看 Microsoft 的这篇文章 -> https://support.microsoft.com/en-us/kb/175574

成本可能在 'Type' 列中,也许您可​​以将其编入索引 -> How to create an index for a string column in sql?

嗯,怎么了:

SELECT [Year],
       [Month],
       [Type],
       COUNT(ClientID) "Count",
       SUM(Cost) "TotalCost",
       ...           
FROM dbo.Example
GROUP BY [Year],[Month],[Type]

你这样做的方式是去规范化它。这就是性能如此差的原因。当然,您在 Type = 'Quotation' 时生成 SUM(Cost) 并且您可能不需要它,但是添加通常不是查询性能的限制因素。

有什么理由让你必须每个[Year],[Month]只有一个记录吗?

根据我的经验,当您遇到如此复杂且具有大量条件聚合的内容时,如果您以逐步的方式构建它,它会更快、更清晰。也就是说,拥有一个具有所需数据结构的 table 变量,并使用避免使用 CASE 语句的单个查询向其添加记录,并(希望)根据索引列进行记录选择。

因此,如果您有一个名为 @TypeTotals 的 table 变量,您可以这样做(使用您的简化示例):

 INSERT INTO @TypeTotals
    SELECT [Year],
           [Month],
           [Type],
           COUNT(ClientID),
           Null,
           Null
    FROM   dbo.Example
    WHERE  [Type] = 'Quotation'
    GROUP BY
           [Year], [Month]

 INSERT INTO @TypeTotals
    SELECT [Year],
           [Month],
           [Type],
           Null,
           COUNT(ClientID),
           SUM(Cost)
    FROM   dbo.Example
    WHERE  [Type] = 'Purchase'
    GROUP BY
           [Year], [Month]

... etc ...

然后您可以总结 @TypeTotals 的内容。

提高速度的关键是避免那些 CASE 语句(正如您已经知道的那样)并充分利用索引。

并进行实验。如果可以,请使用 Profiler,因为执行计划并不总是代表您真正获得的速度。