简体   繁体   English

聚合SQL SELECT语句中的重复案例

[英]Repetitive CASE WHEN in Aggregate SQL SELECT Statements

I am trying to to reduce cost and size of a query I use regularly, it looks far too repetitive to be the most efficient way of doing things. 我试图减少我经常使用的查询的成本和大小,它看起来过于重复,以致无法成为最有效的处理方式。

A simplified representation can be seen below: 简化表示如下:

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]

It is the CASE WHEN ... THEN ELSE NULL END 's that I think I must be able to trim down, in terms of size and cost. 我认为我必须能够精简其尺寸和成本,这是CASE WHEN ... THEN ELSE NULL ENDCASE WHEN ... THEN ELSE NULL END Any recommendations? 有什么建议吗?

I am using SQL Server 2008 R2, Thanks. 我正在使用SQL Server 2008 R2,谢谢。

How about making a view by type ? 如何按类型进行视图? (Quotation, purchase, etc). (报价,购买等)。 In that way, you can optimize view by view and make a join query to get what you want. 这样,您可以逐视图优化视图并进行联接查询以获取所需的内容。

I think that is the recommended way to 'rotate' a table. 我认为这是“旋转”桌子的推荐方法。

Check this article from Microsoft -> https://support.microsoft.com/en-us/kb/175574 从Microsoft-> https://support.microsoft.com/zh-cn/kb/175574查看本文

Probably the cost is in the 'Type' column, maybe you can index that -> How to create an index for a string column in sql? 费用可能在“类型”列中,也许您可​​以为该索引建立-> 如何在sql中为字符串列创建索引?

Erm, what's wrong with: 嗯,怎么了?

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

The way you're doing it is de-normalizing it. 您执行此操作的方式是对其进行非规范化。 That's why the performance is so poor. 这就是为什么性能如此差的原因。 Sure, you're generating SUM(Cost) when Type = 'Quotation' and you might not need that, but addition is not typically a limiting factor for query performance. 当然,当Type = 'Quotation'时,您正在生成SUM(Cost) ,并且可能不需要,但是添加通常不是查询性能的限制因素。

Is there some reason you must have only one record for each [Year],[Month] ? 是否出于某些原因,您每个[Year],[Month]必须有一个记录?

When you've got something that complex, with lots of conditional aggregates, in my experience it's faster and clearer if you build it in a stepwise way. 根据您的经验,如果您遇到的复杂的事情很多,并且有很多条件聚集,那么以逐步的方式构建它会更快,更清晰。 That is, have a table variable with the required data structure, and add records to it with individual queries that avoid using CASE statements and (hopefully) do their record selection based on indexed columns. 也就是说,拥有一个具有所需数据结构的表变量,并通过避免使用CASE语句的单个查询向其中添加记录,并(希望)基于索引列进行记录选择。

So, if you had a table variable called @TypeTotals , you could do something like this (using your simplified example): 因此,如果您有一个名为@TypeTotals的表变量,则可以执行以下操作(使用简化的示例):

 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 ...

You could then summarize the contents of @TypeTotals . 然后,您可以总结@TypeTotals的内容。

The key to speed would be to avoid those CASE statements (as you already figured out) and to make what use you can of indexes. 加快速度的关键是避免使用那些CASE语句(正如您已经知道的那样),并充分利用索引。

And to experiment. 并进行实验。 Make use of the Profiler, if you can, because execution plans don't always represent the speeds you really will get. 如果可能的话,请使用Profiler,因为执行计划并不总是代表您真正将获得的速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM