计算按ID分组的行日期之间的平均时间的有效方法

时间:2014-10-20 12:26:11

标签: sql tsql date group-by average

假设我有一个这样的表:

thedate                   ID 
2014-10-20 14:13:42.063   1
2014-10-20 14:13:43.063   1
2014-10-20 14:13:47.063   1
2014-10-20 14:12:50.063   2
2014-10-20 14:13:49.063   2
2014-10-20 14:13:54.063   2
2014-10-20 14:20:24.063   2
2014-10-20 14:13:02.063   3

要复制与此示例中类似的toybox表,您可以使用以下代码:

declare @tmp as table(thedate datetime,ID int)
insert into @tmp (thedate, ID) values
    (dateadd(s,0,getdate()),1), (dateadd(s,1,getdate()),1), (dateadd(s,5,getdate()),1),
     (dateadd(s,-52,getdate()),2), (dateadd(s,7,getdate()),2), (dateadd(s,12,getdate()),2),(dateadd(s,402,getdate()),2),
     (dateadd(s,-40,getdate()),3)

对于每个ID,我想要日期之间的平均时间。现在数据库很庞大(每个ID的ID和日期很多),所以它必须非常高效。我想要一个这样的结果:

ID  AvgTime (seconds)
 1  2,5
 2  151,333333333333
 3  NULL

以下代码可以满足我的需求,但速度太慢了:

select
   a.ID,
   (select top 1 avg(cast(datediff(s,(select max(thedate) 
                                         from @tmp c where ID = b.ID 
                                             and thedate < b.thedate)
                                     ,thedate) as float)) over (partition by b.ID)
       from @tmp b where ID = a.ID)
from @tmp a group by ID

有谁知道如何有效地做到这一点?

1 个答案:

答案 0 :(得分:1)

平均值是最大值减去最小值除以计数值的1。您可以使用它来编写一个相对简单的查询:

select id,
       cast(datediff(second, min(thedate), max(thedate)) as float) / (count(*) - 1)
from @tmp
group by id;

如果某些ID只有一行,那么您想要检查可能的除以0:

select id,
       (case when count(*) > 1
             then cast(datediff(second, min(thedate), max(thedate)) as float) / (count(*) - 1)
        end) as AvgDiff
from @tmp
group by id;