SQL Server聚合案例语句的替代方案

SQL Server聚合案例语句的替代方案,sql,sql-server,tsql,Sql,Sql Server,Tsql,我创建了一个基于案例表达式进行聚合的视图。视图所基于的事务表大约有9亿行。我需要根据多个标准(包括日期和产品代码)聚合值。我需要至少对数据进行一次完整扫描,就像我们在不使用过滤器的情况下进行聚合一样,所以我认为使用case语句将允许它只进行一次扫描,而不必为每个条件运行查询 我发现,有这么多聚合的case语句真的会减慢速度 下面是一个只有2列的查询示例(在实际查询中可能有50列) 为清晰起见,请编辑问题: 除了聚合CASE表达式之外,还有其他更有效的方法吗?请记住,我至少要对表进行一次完整读取?

我创建了一个基于案例表达式进行聚合的视图。视图所基于的事务表大约有9亿行。我需要根据多个标准(包括日期和产品代码)聚合值。我需要至少对数据进行一次完整扫描,就像我们在不使用过滤器的情况下进行聚合一样,所以我认为使用case语句将允许它只进行一次扫描,而不必为每个条件运行查询

我发现,有这么多聚合的case语句真的会减慢速度

下面是一个只有2列的查询示例(在实际查询中可能有50列)

为清晰起见,请编辑问题:

除了聚合CASE表达式之外,还有其他更有效的方法吗?请记住,我至少要对表进行一次完整读取?我认为我的主要问题是不同CASE表达式的所有嵌套循环,每个新CASE表达式似乎都会增加相当多的成本。如果我对具有2个CASE表达式和50个CASE表达式的相同条件的查询执行估计执行计划,则第一个查询显示20%的成本,第二个查询显示80%的批处理成本

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


谢谢

首先,您的查询是错误的。 它将给出错误的输出

二是使用不明确

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

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.I是否错误/正确


如果您需要使用DISTINCT,则使用CTE筛选重复记录,使用单个DISTINCT或row_number()覆盖(按类别划分,按事务日期顺序)rn

首先,您的查询是错误的。 它将给出错误的输出

二是使用不明确

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

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.I是否错误/正确



如果您需要使用DISTINCT,则使用CTE筛选重复记录,使用单个DISTINCT或row_number()覆盖(按类别划分,按事务日期顺序)rn

按ContactID+类别+生命期+所需事务日期间隔(如td_年、td_月、td_日)分组更有效+您需要作为标准的任何其他字段。然后使用标准聚合,并最终使用适合您的任何技术(使用临时表、嵌套选择、视图等)从外部选择中选择按ContactID分组。

根据ContactID+类别+生命阶段+您需要的交易日期间隔(如td_年、td_月、td_日)+任何其他标准字段进行分组更有效。然后使用标准聚合,并最终使用适合您的任何技术(使用、临时表、嵌套选择、视图等)从外部选择中通过ContactID选择该集合组。

您能否摆脱
计数(不同)
?此外,您不能将
日期添加(DAY,DATEDIFF(DAY,0,GETDATE()),0)
替换为
GETDATE()
?不知道你想用它做什么?或者执行:
CAST(GETDATE()AS DATE)
No在这种情况下不能去掉distinct。dateadd正在从日期中剥离时间。是的,我可以做cast(GetDate()作为Date),但是我的研究表明dateadd方法更有效。你能摆脱
count(distinct)
?另外,你不能用
GetDate()替换
dateadd(DAY,DATEDIFF(DAY,0,GetDate()),0)
?不知道你想用它做什么?或者执行:
CAST(GETDATE()AS DATE)
No在这种情况下不能去掉distinct。dateadd正在从日期中剥离时间。是的,我可以做cast(GetDate()as Date),但是我的研究表明dateadd方法更有效。你能具体解释一下为什么我的输出是错误的吗?我需要区分,因为交易中购买的每个产品都会多次返回交易日期。我只想计算满足条件的唯一日期数。不是每行。我返回不符合条件的空值,因为计数不计算空值。@Bee_Riii,检查我的答案。顺便问一下,我的输出是否错误?你的答案不包括该列。尝试从(选择1个ExampleColumn union all select NULL作为ExampleColumn)t4Great@Bee_Riii中选择计数(ExampleColumn),这是一个愚蠢的错误。记住这一点非常重要。谢谢。我的输出和性能如何?我无法测试您的输出性能,因为它与我的输出不同。谢谢你的帮助。你能具体解释一下为什么我的输出是错误的吗?我需要区分,因为交易中购买的每个产品都会多次返回交易日期。我只想计算满足条件的唯一日期数。不是每行。我返回不符合条件的空值,因为计数不计算空值。@Bee_Riii,检查我的答案。顺便问一下,我的输出是否错误?你的答案不包括该列。尝试从(选择1个ExampleColumn union all select NULL作为ExampleColumn)t4Great@Bee_Riii中选择计数(ExampleColumn),这是一个愚蠢的错误。记住这一点非常重要。谢谢。我的输出和性能如何?我无法测试您的输出性能,因为它与我的输出不同。谢谢你的帮助。