日期范围计数表分组,性能不佳

时间:2013-06-16 22:34:37

标签: sql sql-server-2008 tsql stored-procedures group-by

我有一个存储过程,目前正在非常难以点击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?临时表?其他魔法?

1 个答案:

答案 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