Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL:将行折叠为总和[性能]_Sql_Sql Server_Performance_Sql Server 2008 R2_Subquery - Fatal编程技术网

SQL:将行折叠为总和[性能]

SQL:将行折叠为总和[性能],sql,sql-server,performance,sql-server-2008-r2,subquery,Sql,Sql Server,Performance,Sql Server 2008 R2,Subquery,首先,对于我的问题,我有一个非常有效的解决方案,只是速度不够快 我的数据是每小时的时间卡,每次一周 create table WeeklyHours ( Id int identity(1,1) not null, ResourceID int not null, WeekOf datetime not null, Sunday decimal(8, 5) not null, Monday decimal(8, 5) not null, Tuesd

首先,对于我的问题,我有一个非常有效的解决方案,只是速度不够快

我的数据是每小时的时间卡,每次一周

create table WeeklyHours
(
    Id int identity(1,1) not null,
    ResourceID int not null,
    WeekOf datetime not null,
    Sunday decimal(8, 5) not null,
    Monday decimal(8, 5) not null,
    Tuesday decimal(8, 5) not null,
    Wednesday decimal(8, 5) not null,
    Thursday decimal(8, 5) not null,
    Friday decimal(8, 5) not null,
    Saturday decimal(8, 5) not null,
    Total decimal(8, 5) not null,
    BufferFor int null,
)
我们的制度允许的是,如果一个人生病了,另一个人可以代替他们。这称为缓冲。BufferFor字段将是被保险人的ResourceID,如果是正常工作时间,则为空

我要做的是将缓冲行折叠为常规工作时间。我们保证会有固定的工作时间排,即使都是0

以下是我是如何做到这一点的:表格按日期范围内的适用行进行筛选:

select 
    WH.ResourceID, 
    WeekOf, 
    Monday + ISNULL((select SUM(Monday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as M, 
    Tuesday + ISNULL((select SUM(Tuesday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as T, 
    Wednesday + ISNULL((select SUM(Wednesday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as W, 
    Thursday + ISNULL((select SUM(Thursday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as R, 
    Friday + ISNULL((select SUM(Friday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as F, 
    Saturday + ISNULL((select SUM(Saturday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as S, 
    Sunday + ISNULL((select SUM(Sunday) from WeeklyHours WH2 where WH2.BufferFor = WH.ResourceID and WH2.WeekOf = WH.WeekOf),0) as U,
from
    WeeklyHours WH
where 
    WH.WeekOf >= @applicableMonday
    and WH.WeekOf <= @lastDay
我在Id上有一个群集主键

我在ResourceID WeekOf上有一个非聚集索引,它也有用于子选择的Mon-Sun小时数和缓冲区

这方面的表现还行,不算糟糕,但也不是很好。运行我的Func的总成本约为.2019秒。这个查询大约是Func总成本的65%,在过滤掉缓冲区行后,只返回约5500行。但是,由于这最终会被另一个进程调用约2000次,因此最终会花费我约7分钟的时间

有没有更快的方法?
谢谢

你的表演相当不错。你的问题是,在你提到的大爆炸中,你被一些听起来像是糟糕的编码所滥用。因此,假设您设法将查询的性能提高了90%,并且在存储过程开始调用查询20000次后不久。。。你回到了起点

我会从调查问题的大讨论开始,看看是否有比在短时间内拨打数千个电话更好的解决方案。作为一个简单的例子,这可能是一个不从循环调用查询的简单修复。客户机代码还可以使用缓存,而不是对变化不大的数据重复调用查询

如果您想遵循性能路线,那么我建议进行非规范化。因为查询结果是按周装箱的,所以反规范化实际上是一个很好的解决方案。您将创建另一个表并用查询结果填充它。。。您也不会一直调用巡更子查询。SQLServer通常会为此进行优化,但这绝对值得一试


祝你好运

主键聚集[Id]ASC带PAD\u INDEX=OFF,STATISTICS\u norecocomputer=OFF,IGNORE\u DUP\u KEY=OFF,ALLOW\u ROW\u LOCKS=ON,ALLOW\u PAGE\u LOCKS=ON ON[PRIMARY]ON[PRIMARY]关于ResourceID的问题中的索引,WeekOf不是聚集的,应该吗?也许你可以找到一种方法,不调用这2000次。这似乎是性能杀手。我同意,我的func设计用于计算单个资源或单个项目上所有资源的两个日期之间的成本。这就是为什么它被称为12*Number of Projects(项目数),也就是说,对于其中一个视图,每个项目每个会计月一次。因此,取消Pivot并为列信息获取类似的内容:ResourceID、Date、Hours、BufferFor,然后以某种方式进行折叠?另外,另一个存储过程保证给我打电话的次数相当固定。每个项目每月一次。我们目前有约165个项目,预计不会大幅增长。最多2倍。著名的遗言。。。洛尔并不是完全的unpivot。如您所示,您的非规范化表实际上看起来与原始表类似,但添加了WeekId列以创建week Bucket。您还需要提前完成所有ISNULL逻辑。您是说添加WeekID并删除WeekOf,然后为实际日期创建另一个表?小鬼,小鬼?一般来说,仍然只有一对WeekID,ResourceID。我可以使用CTE来选择缓冲区行吗?看起来可能有用。@ohmusama:对不起,我开始忘记OP了。但简而言之,您需要创建一个表,该表没有任何类型的残缺,在查询时,不需要连接,不需要计算,无空检查等。对该表的查询应仅通过您选择的任何方法来跟踪周桶来指定周。使用CTE很好,但如何获得干净的数据不如最终数据重要。