2014-10-20 69 views
0

分组行日期之间的平均时间假设我有一个像这样的表:有效的方式来计算由ID

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

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

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

如果一些IDS的只有一行,那么你会希望通过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; 
+0

这是有益的看看为什么这个工作 - 没有在这里重复,请参阅[这个答案](http://stackoverflow.com/a/5160040/4137916)一个密切相关的问题。 – 2014-10-20 13:12:31

+0

非常感谢 - 谢谢! – 2014-10-28 13:22:13

相关问题