替代聚合案例语句SQL Server

时间:2017-05-11 09:58:15

标签: sql sql-server tsql

我创建了一个基于CASE表达式进行聚合的视图。视图所基于的事务表具有大约9亿行。我需要根据多个条件汇总值,包括日期和产品代码。我需要至少对数据进行一次全面扫描,因为我们在没有过滤器的情况下进行了一些聚合,所以我认为使用case语句只需要进行1次扫描,而不必为每个标准运行查询。

我发现,拥有如此多的汇总案例陈述确实会让事情变得迟钝。

以下是我的查询示例,只有2列(在真实查询中可能有50列)

SELECT  [ContactID] AS [ContactID],
        COUNT(DISTINCT CASE
                           WHEN [Category] = 'Dog Food'
                                AND [TransactionDate]
                                BETWEEN DATEADD(MONTH, -12, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
                                THEN [TransactionDate]
                           ELSE NULL
                       END
            )       AS [Dog_FoodTx12mth],
        COUNT(DISTINCT CASE
                           WHEN [Category] = 'Cat Food'
                                AND [Lifestage] LIKE 'Kitten%'
                                AND [TransactionDate]
                                BETWEEN DATEADD(MONTH, -3, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
                                THEN [TransactionDate]
                           ELSE NULL
                       END
            )       AS [Cat_FoodKittenTx3mth]
FROM    [dbo].[GI_TransactionLineProductContact]
GROUP BY [ContactID];

为清晰起见编辑问题:

是否有另一种方法,而不是聚合CASE表达式,这可能会更有效,请记住,我必须至少进行一次完整的表格读取?我认为我的主要问题是不同CASE表达式的所有嵌套循环,每个新的case表达式似乎都会增加相当多的成本。如果我针对具有2个CASE表达式的相同条件和具有50个CASE表达式的查询执行查询的估计执行计划,则第一个查询显示20%的成本,第二个查询显示80%的批量成本。

所以我认为这个设计可能不是最有效的,我正在寻找可以使用的潜在替代方法。

由于

2 个答案:

答案 0 :(得分:0)

首先你的查询是错误的。 它会给出错误的输出

其次使用DISTINCT并不清楚。

尝试我的脚本,如果你没有得到正确的输出,那么你可以放回DISTINCT

SELECT  [ContactID] AS [ContactID],
        sum( CASE
                           WHEN [Category] = 'Dog Food'
                                AND [TransactionDate]
                                BETWEEN DATEADD(MONTH, -12, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
                                THEN 1
                           ELSE 0
                       END
            )       AS [Dog_FoodTx12mth],
        SUM(CASE
                           WHEN [Category] = 'Cat Food'
                                AND [Lifestage] LIKE 'Kitten%'
                                AND [TransactionDate]
                                BETWEEN DATEADD(MONTH, -3, DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) AND DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
                                THEN 1
                           ELSE 0
                       END
            )       AS [Cat_FoodKittenTx3mth]
FROM    [dbo].[GI_TransactionLineProductContact]
GROUP BY [ContactID];

为什么您的查询可能有误?

select count(*) from
(
select 1 col
union all
select null
)t4

输出返回是2.desire output = 1.Am我错了/正确吗?

如果您使用DISTINCT然后使用CTE过滤器重复记录使用单个distinct或row_number()over(按类别分区,按事务日期的transactiondate顺序)rn

答案 1 :(得分:0)

通过ContactID + Category + Lifestage +您需要的TransactionDate间隔(例如td_year,td_month,td_day)+您需要的任何其他字段作为条件进行分组更有效。然后使用标准聚合,最后使用适合您的外部选择(Contact,临时表,嵌套选择,视图......),通过ContactID从ContactID中选择该组。