我有一个存储过程,目前正在非常难以点击TempDb,使查询运行速度慢,有时会消耗大量磁盘空间(增长的TempDb)。我正在采取这样的数据:
ID StartDate EndDate
----------- ----------------------- -----------------------
1 2013-06-17 00:09:59.270 2013-09-25 00:09:59.270
2 2013-06-22 00:10:30.077 2013-07-22 00:10:30.077
并且需要按照项目(ID),年份和月份对其进行分组,并根据源数据中的范围保留每月的天数,希望最终得到这个(减去我的深夜计算错误)部分):
ID TheYear TheMonth NumberOfDays
--- ------- ----------- ------------
1 2013 6 14
1 2013 7 31
1 2013 8 31
1 2013 9 25
2 2013 6 9
2 2013 7 22
今天使用与此类似的存储过程完成此计算:
INSERT INTO GroupedData
(
ID,
TheYear ,
TheMonth ,
NumberOfDays
)
SELECT ID,
YEAR(StartDate + v.number) AS TheYear,
MONTH(StartDate + v.number) AS TheMonth,
COUNT(*) AS NumberOfDays
FROM dbo.RawData
INNER JOIN
master..spt_values v ON v.type = 'P'
AND v.number <= DATEDIFF(d, StartDate, EndDate)
GROUP BY ID,
YEAR(StartDate + v.number),
MONTH(StartDate + v.number)
现在,这似乎在计算方面做得很好,但效果不是很好。它消耗大量磁盘(TempDb)和CPU资源。输入表在100'000到100万行之间。实际来源日期范围低于50年,通常为5 - 10年。
我的猜测是使用Tally表(master..spt_values
)连接会导致查询超出比例。注意:我在实际代码中使用生成的“数字”表来处理Tally表仅包含2048个条目的事实。
那么,有更好的方法来进行此计算吗?游标? CTE?临时表?其他魔法?
答案 0 :(得分:0)
试试这个
INSERT INTO GroupedData
(
ID,
TheYear ,
TheMonth ,
NumberOfDays
)
SELECT ID,
YEAR(StartDate) + v.number AS TheYear,
MONTH(StartDate) + v.number AS TheMonth,
COUNT(*) AS NumberOfDays
FROM dbo.RawData
INNER JOIN
master..spt_values v ON v.type = 'P'
AND v.number <= DATEDIFF(d, StartDate, EndDate)
GROUP BY ID,
YEAR(StartDate) + v.number,
MONTH(StartDate) + v.number